about summary refs log tree commit diff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/admin/domain_allows_controller_spec.rb48
-rw-r--r--spec/controllers/admin/domain_blocks_controller_spec.rb21
-rw-r--r--spec/controllers/admin/export_domain_allows_controller_spec.rb42
-rw-r--r--spec/controllers/admin/export_domain_blocks_controller_spec.rb35
-rw-r--r--spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb4
-rw-r--r--spec/fixtures/files/domain_allows.csv3
-rw-r--r--spec/fixtures/files/domain_blocks.csv4
-rw-r--r--spec/helpers/settings/keyword_mutes_helper_spec.rb15
-rw-r--r--spec/lib/advanced_text_formatter_spec.rb4
-rw-r--r--spec/lib/emoji_formatter_spec.rb6
-rw-r--r--spec/lib/rss/serializer_spec.rb56
-rw-r--r--spec/models/account_spec.rb178
-rw-r--r--spec/services/activitypub/fetch_remote_status_service_spec.rb40
-rw-r--r--spec/services/fetch_remote_status_service_spec.rb6
-rw-r--r--spec/services/resolve_url_service_spec.rb19
15 files changed, 377 insertions, 104 deletions
diff --git a/spec/controllers/admin/domain_allows_controller_spec.rb b/spec/controllers/admin/domain_allows_controller_spec.rb
new file mode 100644
index 000000000..8bacdd3e4
--- /dev/null
+++ b/spec/controllers/admin/domain_allows_controller_spec.rb
@@ -0,0 +1,48 @@
+require 'rails_helper'
+
+RSpec.describe Admin::DomainAllowsController, type: :controller do
+  render_views
+
+  before do
+    sign_in Fabricate(:user, admin: true), scope: :user
+  end
+
+  describe 'GET #new' do
+    it 'assigns a new domain allow' do
+      get :new
+
+      expect(assigns(:domain_allow)).to be_instance_of(DomainAllow)
+      expect(response).to have_http_status(200)
+    end
+  end
+
+  describe 'POST #create' do
+    it 'blocks the domain when succeeded to save' do
+      post :create, params: { domain_allow: { domain: 'example.com' } }
+
+      expect(flash[:notice]).to eq I18n.t('admin.domain_allows.created_msg')
+      expect(response).to redirect_to(admin_instances_path)
+    end
+
+    it 'renders new when failed to save' do
+      Fabricate(:domain_allow, domain: 'example.com')
+
+      post :create, params: { domain_allow: { domain: 'example.com' } }
+
+      expect(response).to render_template :new
+    end
+  end
+
+  describe 'DELETE #destroy' do
+    it 'disallows the domain' do
+      service = double(call: true)
+      allow(UnallowDomainService).to receive(:new).and_return(service)
+      domain_allow = Fabricate(:domain_allow)
+      delete :destroy, params: { id: domain_allow.id }
+
+      expect(service).to have_received(:call).with(domain_allow)
+      expect(flash[:notice]).to eq I18n.t('admin.domain_allows.destroyed_msg')
+      expect(response).to redirect_to(admin_instances_path)
+    end
+  end
+end
diff --git a/spec/controllers/admin/domain_blocks_controller_spec.rb b/spec/controllers/admin/domain_blocks_controller_spec.rb
index ecc79292b..a35b2fb3b 100644
--- a/spec/controllers/admin/domain_blocks_controller_spec.rb
+++ b/spec/controllers/admin/domain_blocks_controller_spec.rb
@@ -16,6 +16,27 @@ RSpec.describe Admin::DomainBlocksController, type: :controller do
     end
   end
 
+  describe 'POST #batch' do
+    it 'blocks the domains when succeeded to save' do
+      allow(DomainBlockWorker).to receive(:perform_async).and_return(true)
+
+      post :batch, params: {
+        save: '',
+        form_domain_block_batch: {
+          domain_blocks_attributes: {
+            '0' => { enabled: '1', domain: 'example.com', severity: 'silence' },
+            '1' => { enabled: '0', domain: 'mastodon.social', severity: 'suspend' },
+            '2' => { enabled: '1', domain: 'mastodon.online', severity: 'suspend' }
+          }
+        }
+      }
+
+      expect(DomainBlockWorker).to have_received(:perform_async).exactly(2).times
+      expect(flash[:notice]).to eq I18n.t('admin.domain_blocks.created_msg')
+      expect(response).to redirect_to(admin_instances_path(limited: '1'))
+    end
+  end
+
   describe 'POST #create' do
     it 'blocks the domain when succeeded to save' do
       allow(DomainBlockWorker).to receive(:perform_async).and_return(true)
diff --git a/spec/controllers/admin/export_domain_allows_controller_spec.rb b/spec/controllers/admin/export_domain_allows_controller_spec.rb
new file mode 100644
index 000000000..f6275c2d6
--- /dev/null
+++ b/spec/controllers/admin/export_domain_allows_controller_spec.rb
@@ -0,0 +1,42 @@
+require 'rails_helper'
+
+RSpec.describe Admin::ExportDomainAllowsController, type: :controller do
+  render_views
+
+  before do
+    sign_in Fabricate(:user, admin: true), scope: :user
+  end
+
+  describe 'GET #export' do
+    it 'renders instances' do
+      Fabricate(:domain_allow, domain: 'good.domain')
+      Fabricate(:domain_allow, domain: 'better.domain')
+
+      get :export, params: { format: :csv }
+      expect(response).to have_http_status(200)
+      expect(response.body).to eq(IO.read(File.join(file_fixture_path, 'domain_allows.csv')))
+    end
+  end
+
+  describe 'POST #import' do
+    it 'allows imported domains' do
+      post :import, params: { admin_import: { data: fixture_file_upload('domain_allows.csv') } }
+
+      expect(response).to redirect_to(admin_instances_path)
+
+      # Header should not be imported
+      expect(DomainAllow.where(domain: '#domain').present?).to eq(false)
+
+      # Domains should now be added
+      get :export, params: { format: :csv }
+      expect(response).to have_http_status(200)
+      expect(response.body).to eq(IO.read(File.join(file_fixture_path, 'domain_allows.csv')))
+    end
+
+    it 'displays error on no file selected' do
+      post :import, params: { admin_import: {} }
+      expect(response).to redirect_to(admin_instances_path)
+      expect(flash[:error]).to eq(I18n.t('admin.export_domain_allows.no_file'))
+    end
+  end
+end
diff --git a/spec/controllers/admin/export_domain_blocks_controller_spec.rb b/spec/controllers/admin/export_domain_blocks_controller_spec.rb
new file mode 100644
index 000000000..0493df859
--- /dev/null
+++ b/spec/controllers/admin/export_domain_blocks_controller_spec.rb
@@ -0,0 +1,35 @@
+require 'rails_helper'
+
+RSpec.describe Admin::ExportDomainBlocksController, type: :controller do
+  render_views
+
+  before do
+    sign_in Fabricate(:user, admin: true), scope: :user
+  end
+
+  describe 'GET #export' do
+    it 'renders instances' do
+      Fabricate(:domain_block, domain: 'bad.domain', severity: 'silence', public_comment: 'bad')
+      Fabricate(:domain_block, domain: 'worse.domain', severity: 'suspend', reject_media: true, reject_reports: true, public_comment: 'worse', obfuscate: true)
+      Fabricate(:domain_block, domain: 'reject.media', severity: 'noop', reject_media: true, public_comment: 'reject media')
+      Fabricate(:domain_block, domain: 'no.op', severity: 'noop', public_comment: 'noop')
+
+      get :export, params: { format: :csv }
+      expect(response).to have_http_status(200)
+      expect(response.body).to eq(IO.read(File.join(file_fixture_path, 'domain_blocks.csv')))
+    end
+  end
+
+  describe 'POST #import' do
+    it 'blocks imported domains' do
+      post :import, params: { admin_import: { data: fixture_file_upload('domain_blocks.csv') } }
+
+      expect(assigns(:domain_blocks).map(&:domain)).to match_array ['bad.domain', 'worse.domain', 'reject.media']
+    end
+  end
+
+  it 'displays error on no file selected' do
+    post :import, params: { admin_import: {} }
+    expect(flash[:alert]).to eq(I18n.t('admin.export_domain_blocks.no_file'))
+  end
+end
diff --git a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb
index 7b86513be..569c8322b 100644
--- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb
+++ b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb
@@ -22,7 +22,7 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do
     let(:user) { Fabricate(:user, email: 'local-part@domain', otp_secret: with_otp_secret ? 'oldotpsecret' : nil) }
 
     describe 'GET #new' do
-      context 'when signed in and a new otp secret has been setted in the session' do
+      context 'when signed in and a new otp secret has been set in the session' do
         subject do
           sign_in user, scope: :user
           get :new, session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' }
@@ -36,7 +36,7 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do
         expect(response).to redirect_to('/auth/sign_in')
       end
 
-      it 'redirects if a new otp_secret has not been setted in the session' do
+      it 'redirects if a new otp_secret has not been set in the session' do
         sign_in user, scope: :user
         get :new, session: { challenge_passed_at: Time.now.utc }
         expect(response).to redirect_to('/settings/otp_authentication')
diff --git a/spec/fixtures/files/domain_allows.csv b/spec/fixtures/files/domain_allows.csv
new file mode 100644
index 000000000..4200ac3f5
--- /dev/null
+++ b/spec/fixtures/files/domain_allows.csv
@@ -0,0 +1,3 @@
+#domain
+good.domain
+better.domain
diff --git a/spec/fixtures/files/domain_blocks.csv b/spec/fixtures/files/domain_blocks.csv
new file mode 100644
index 000000000..28ffb9175
--- /dev/null
+++ b/spec/fixtures/files/domain_blocks.csv
@@ -0,0 +1,4 @@
+#domain,#severity,#reject_media,#reject_reports,#public_comment,#obfuscate
+bad.domain,silence,false,false,bad,false
+worse.domain,suspend,true,true,worse,true
+reject.media,noop,true,false,reject media,false
diff --git a/spec/helpers/settings/keyword_mutes_helper_spec.rb b/spec/helpers/settings/keyword_mutes_helper_spec.rb
deleted file mode 100644
index a19d518dd..000000000
--- a/spec/helpers/settings/keyword_mutes_helper_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'rails_helper'
-
-# Specs in this file have access to a helper object that includes
-# the Settings::KeywordMutesHelper. For example:
-#
-# describe Settings::KeywordMutesHelper do
-#   describe "string concat" do
-#     it "concats two strings with spaces" do
-#       expect(helper.concat_strings("this","that")).to eq("this that")
-#     end
-#   end
-# end
-RSpec.describe Settings::KeywordMutesHelper, type: :helper do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/lib/advanced_text_formatter_spec.rb b/spec/lib/advanced_text_formatter_spec.rb
index ea1a9570d..3255fc927 100644
--- a/spec/lib/advanced_text_formatter_spec.rb
+++ b/spec/lib/advanced_text_formatter_spec.rb
@@ -40,6 +40,10 @@ RSpec.describe AdvancedTextFormatter do
         it 'formats code using <pre> and <code>' do
           is_expected.to include '<pre><code>int main'
         end
+
+        it 'does not strip leading spaces' do
+          is_expected.to include '>  return 0'
+        end
       end
 
       context 'given some quote' do
diff --git a/spec/lib/emoji_formatter_spec.rb b/spec/lib/emoji_formatter_spec.rb
index 129445aa5..e1747bdd9 100644
--- a/spec/lib/emoji_formatter_spec.rb
+++ b/spec/lib/emoji_formatter_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe EmojiFormatter do
       let(:text) { preformat_text(':coolcat: Beep boop') }
 
       it 'converts the shortcode to an image tag' do
-        is_expected.to match(/<img draggable="false" class="emojione custom-emoji" alt=":coolcat:"/)
+        is_expected.to match(/<img rel="emoji" draggable="false" width="16" height="16" class="emojione custom-emoji" alt=":coolcat:"/)
       end
     end
 
@@ -32,7 +32,7 @@ RSpec.describe EmojiFormatter do
       let(:text) { preformat_text('Beep :coolcat: boop') }
 
       it 'converts the shortcode to an image tag' do
-        is_expected.to match(/Beep <img draggable="false" class="emojione custom-emoji" alt=":coolcat:"/)
+        is_expected.to match(/Beep <img rel="emoji" draggable="false" width="16" height="16" class="emojione custom-emoji" alt=":coolcat:"/)
       end
     end
 
@@ -48,7 +48,7 @@ RSpec.describe EmojiFormatter do
       let(:text) { preformat_text('Beep boop :coolcat:') }
 
       it 'converts the shortcode to an image tag' do
-        is_expected.to match(/boop <img draggable="false" class="emojione custom-emoji" alt=":coolcat:"/)
+        is_expected.to match(/boop <img rel="emoji" draggable="false" width="16" height="16" class="emojione custom-emoji" alt=":coolcat:"/)
       end
     end
   end
diff --git a/spec/lib/rss/serializer_spec.rb b/spec/lib/rss/serializer_spec.rb
deleted file mode 100644
index 1da45d302..000000000
--- a/spec/lib/rss/serializer_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe RSS::Serializer do
-  describe '#status_title' do
-    let(:text)      { 'This is a toot' }
-    let(:spoiler)   { '' }
-    let(:sensitive) { false }
-    let(:reblog)    { nil }
-    let(:account)   { Fabricate(:account) }
-    let(:status)    { Fabricate(:status, account: account, text: text, spoiler_text: spoiler, sensitive: sensitive, reblog: reblog) }
-
-    subject { RSS::Serializer.new.send(:status_title, status) }
-
-    context 'on a toot with long text' do
-      let(:text) { "This toot's text is longer than the allowed number of characters" }
-
-      it 'truncates toot text appropriately' do
-        expect(subject).to eq "#{account.acct}: “This toot's text is longer tha…”"
-      end
-    end
-
-    context 'on a toot with long text with a newline' do
-      let(:text) { "This toot's text is longer\nthan the allowed number of characters" }
-
-      it 'truncates toot text appropriately' do
-        expect(subject).to eq "#{account.acct}: “This toot's text is longer…”"
-      end
-    end
-
-    context 'on a toot with a content warning' do
-      let(:spoiler) { 'long toot' }
-
-      it 'displays spoiler text instead of toot content' do
-        expect(subject).to eq "#{account.acct}: CW “long toot”"
-      end
-    end
-
-    context 'on a toot with sensitive media' do
-      let(:sensitive) { true }
-
-      it 'displays that the media is sensitive' do
-        expect(subject).to eq "#{account.acct}: “This is a toot” (sensitive)"
-      end
-    end
-
-    context 'on a reblog' do
-      let(:reblog) { Fabricate(:status, text: 'This is a toot') }
-
-      it 'display that the toot is a reblog' do
-        expect(subject).to eq "#{account.acct} boosted #{reblog.account.acct}: “This is a toot”"
-      end
-    end
-  end
-end
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb
index 681134d49..dc0ca3da3 100644
--- a/spec/models/account_spec.rb
+++ b/spec/models/account_spec.rb
@@ -350,6 +350,45 @@ RSpec.describe Account, type: :model do
       )
     end
 
+    it 'does not return suspended users' do
+      match = Fabricate(
+        :account,
+        display_name: 'Display Name',
+        username: 'username',
+        domain: 'example.com',
+        suspended: true
+      )
+
+      results = Account.search_for('username')
+      expect(results).to eq []
+    end
+
+    it 'does not return unapproved users' do
+      match = Fabricate(
+        :account,
+        display_name: 'Display Name',
+        username: 'username'
+      )
+
+      match.user.update(approved: false)
+
+      results = Account.search_for('username')
+      expect(results).to eq []
+    end
+
+    it 'does not return unconfirmed users' do
+      match = Fabricate(
+        :account,
+        display_name: 'Display Name',
+        username: 'username'
+      )
+
+      match.user.update(confirmed_at: nil)
+
+      results = Account.search_for('username')
+      expect(results).to eq []
+    end
+
     it 'accepts ?, \, : and space as delimiter' do
       match = Fabricate(
         :account,
@@ -422,8 +461,114 @@ RSpec.describe Account, type: :model do
   end
 
   describe '.advanced_search_for' do
+    let(:account) { Fabricate(:account) }
+
+    context 'when limiting search to followed accounts' do
+      it 'accepts ?, \, : and space as delimiter' do
+        match = Fabricate(
+          :account,
+          display_name: 'A & l & i & c & e',
+          username: 'username',
+          domain: 'example.com'
+        )
+        account.follow!(match)
+
+        results = Account.advanced_search_for('A?l\i:c e', account, 10, true)
+        expect(results).to eq [match]
+      end
+
+      it 'does not return non-followed accounts' do
+        match = Fabricate(
+          :account,
+          display_name: 'A & l & i & c & e',
+          username: 'username',
+          domain: 'example.com'
+        )
+
+        results = Account.advanced_search_for('A?l\i:c e', account, 10, true)
+        expect(results).to eq []
+      end
+
+      it 'does not return suspended users' do
+        match = Fabricate(
+          :account,
+          display_name: 'Display Name',
+          username: 'username',
+          domain: 'example.com',
+          suspended: true
+        )
+
+        results = Account.advanced_search_for('username', account, 10, true)
+        expect(results).to eq []
+      end
+
+      it 'does not return unapproved users' do
+        match = Fabricate(
+          :account,
+          display_name: 'Display Name',
+          username: 'username'
+        )
+
+        match.user.update(approved: false)
+
+        results = Account.advanced_search_for('username', account, 10, true)
+        expect(results).to eq []
+      end
+
+      it 'does not return unconfirmed users' do
+        match = Fabricate(
+          :account,
+          display_name: 'Display Name',
+          username: 'username'
+        )
+
+        match.user.update(confirmed_at: nil)
+
+        results = Account.advanced_search_for('username', account, 10, true)
+        expect(results).to eq []
+      end
+    end
+
+    it 'does not return suspended users' do
+      match = Fabricate(
+        :account,
+        display_name: 'Display Name',
+        username: 'username',
+        domain: 'example.com',
+        suspended: true
+      )
+
+      results = Account.advanced_search_for('username', account)
+      expect(results).to eq []
+    end
+
+    it 'does not return unapproved users' do
+      match = Fabricate(
+        :account,
+        display_name: 'Display Name',
+        username: 'username'
+      )
+
+      match.user.update(approved: false)
+
+      results = Account.advanced_search_for('username', account)
+      expect(results).to eq []
+    end
+
+    it 'does not return unconfirmed users' do
+      match = Fabricate(
+        :account,
+        display_name: 'Display Name',
+        username: 'username'
+      )
+
+      match.user.update(confirmed_at: nil)
+
+      results = Account.advanced_search_for('username', account)
+      expect(results).to eq []
+    end
+
     it 'accepts ?, \, : and space as delimiter' do
-      account = Fabricate(:account)
       match = Fabricate(
         :account,
         display_name: 'A & l & i & c & e',
@@ -437,18 +582,17 @@ RSpec.describe Account, type: :model do
 
     it 'limits by 10 by default' do
       11.times { Fabricate(:account, display_name: "Display Name") }
-      results = Account.search_for("display")
+      results = Account.advanced_search_for("display", account)
       expect(results.size).to eq 10
     end
 
     it 'accepts arbitrary limits' do
       2.times { Fabricate(:account, display_name: "Display Name") }
-      results = Account.search_for("display", 1)
+      results = Account.advanced_search_for("display", account, 1)
       expect(results.size).to eq 1
     end
 
     it 'ranks followed accounts higher' do
-      account = Fabricate(:account)
       match = Fabricate(:account, username: "Matching")
       followed_match = Fabricate(:account, username: "Matcher")
       Fabricate(:follow, account: account, target_account: followed_match)
@@ -775,6 +919,32 @@ RSpec.describe Account, type: :model do
         expect(Account.suspended).to match_array([account_1])
       end
     end
+
+    describe 'searchable' do
+      let!(:suspended_local)        { Fabricate(:account, suspended: true, username: 'suspended_local') }
+      let!(:suspended_remote)       { Fabricate(:account, suspended: true, domain: 'example.org', username: 'suspended_remote') }
+      let!(:silenced_local)         { Fabricate(:account, silenced: true, username: 'silenced_local') }
+      let!(:silenced_remote)        { Fabricate(:account, silenced: true, domain: 'example.org', username: 'silenced_remote') }
+      let!(:unconfirmed)            { Fabricate(:user, confirmed_at: nil).account }
+      let!(:unapproved)             { Fabricate(:user, approved: false).account }
+      let!(:unconfirmed_unapproved) { Fabricate(:user, confirmed_at: nil, approved: false).account }
+      let!(:local_account)          { Fabricate(:account, username: 'local_account') }
+      let!(:remote_account)         { Fabricate(:account, domain: 'example.org', username: 'remote_account') }
+
+      before do
+        # Accounts get automatically-approved depending on settings, so ensure they aren't approved
+        unapproved.user.update(approved: false)
+        unconfirmed_unapproved.user.update(approved: false)
+      end
+
+      it 'returns every usable non-suspended account' do
+        expect(Account.searchable).to match_array([silenced_local, silenced_remote, local_account, remote_account])
+      end
+
+      it 'does not mess with previously-applied scopes' do
+        expect(Account.where.not(id: remote_account.id).searchable).to match_array([silenced_local, silenced_remote, local_account])
+      end
+    end
   end
 
   context 'when is local' do
diff --git a/spec/services/activitypub/fetch_remote_status_service_spec.rb b/spec/services/activitypub/fetch_remote_status_service_spec.rb
index 943cb161d..7359ca0b4 100644
--- a/spec/services/activitypub/fetch_remote_status_service_spec.rb
+++ b/spec/services/activitypub/fetch_remote_status_service_spec.rb
@@ -3,16 +3,15 @@ require 'rails_helper'
 RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
   include ActionView::Helpers::TextHelper
 
-  let!(:sender) { Fabricate(:account).tap { |account| account.update(uri: ActivityPub::TagManager.instance.uri_for(account)) } }
+  let!(:sender) { Fabricate(:account, domain: 'foo.bar', uri: 'https://foo.bar') }
   let!(:recipient) { Fabricate(:account) }
-  let!(:valid_domain) { Rails.configuration.x.local_domain }
 
   let(:existing_status) { nil }
 
   let(:note) do
     {
       '@context': 'https://www.w3.org/ns/activitystreams',
-      id: "https://#{valid_domain}/@foo/1234",
+      id: "https://foo.bar/@foo/1234",
       type: 'Note',
       content: 'Lorem ipsum',
       attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
@@ -22,7 +21,8 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
   subject { described_class.new }
 
   before do
-    stub_request(:head, 'https://example.com/watch?v=12345').to_return(status: 404, body: '')
+    stub_request(:get, 'https://foo.bar/watch?v=12345').to_return(status: 404, body: '')
+    stub_request(:get, object[:id]).to_return(body: Oj.dump(object))
   end
 
   describe '#call' do
@@ -46,7 +46,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
       let(:object) do
         {
           '@context': 'https://www.w3.org/ns/activitystreams',
-          id: "https://#{valid_domain}/@foo/1234",
+          id: "https://foo.bar/@foo/1234",
           type: 'Video',
           name: 'Nyan Cat 10 hours remix',
           attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
@@ -54,13 +54,13 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
             {
               type: 'Link',
               mimeType: 'application/x-bittorrent',
-              href: "https://#{valid_domain}/12345.torrent",
+              href: "https://foo.bar/12345.torrent",
             },
 
             {
               type: 'Link',
               mimeType: 'text/html',
-              href: "https://#{valid_domain}/watch?v=12345",
+              href: "https://foo.bar/watch?v=12345",
             },
           ],
         }
@@ -70,8 +70,8 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
         status = sender.statuses.first
 
         expect(status).to_not be_nil
-        expect(status.url).to eq "https://#{valid_domain}/watch?v=12345"
-        expect(strip_tags(status.text)).to eq "Nyan Cat 10 hours remixhttps://#{valid_domain}/watch?v=12345"
+        expect(status.url).to eq "https://foo.bar/watch?v=12345"
+        expect(strip_tags(status.text)).to eq "Nyan Cat 10 hours remixhttps://foo.bar/watch?v=12345"
       end
     end
 
@@ -79,7 +79,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
       let(:object) do
         {
           '@context': 'https://www.w3.org/ns/activitystreams',
-          id: "https://#{valid_domain}/@foo/1234",
+          id: "https://foo.bar/@foo/1234",
           type: 'Audio',
           name: 'Nyan Cat 10 hours remix',
           attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
@@ -87,13 +87,13 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
             {
               type: 'Link',
               mimeType: 'application/x-bittorrent',
-              href: "https://#{valid_domain}/12345.torrent",
+              href: "https://foo.bar/12345.torrent",
             },
 
             {
               type: 'Link',
               mimeType: 'text/html',
-              href: "https://#{valid_domain}/watch?v=12345",
+              href: "https://foo.bar/watch?v=12345",
             },
           ],
         }
@@ -103,8 +103,8 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
         status = sender.statuses.first
 
         expect(status).to_not be_nil
-        expect(status.url).to eq "https://#{valid_domain}/watch?v=12345"
-        expect(strip_tags(status.text)).to eq "Nyan Cat 10 hours remixhttps://#{valid_domain}/watch?v=12345"
+        expect(status.url).to eq "https://foo.bar/watch?v=12345"
+        expect(strip_tags(status.text)).to eq "Nyan Cat 10 hours remixhttps://foo.bar/watch?v=12345"
       end
     end
 
@@ -112,7 +112,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
       let(:object) do
         {
           '@context': 'https://www.w3.org/ns/activitystreams',
-          id: "https://#{valid_domain}/@foo/1234",
+          id: "https://foo.bar/@foo/1234",
           type: 'Event',
           name: "Let's change the world",
           attributedTo: ActivityPub::TagManager.instance.uri_for(sender)
@@ -123,8 +123,8 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
         status = sender.statuses.first
 
         expect(status).to_not be_nil
-        expect(status.url).to eq "https://#{valid_domain}/@foo/1234"
-        expect(strip_tags(status.text)).to eq "Let's change the worldhttps://#{valid_domain}/@foo/1234"
+        expect(status.url).to eq "https://foo.bar/@foo/1234"
+        expect(strip_tags(status.text)).to eq "Let's change the worldhttps://foo.bar/@foo/1234"
       end
     end
 
@@ -154,7 +154,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
       let(:object) do
         {
           '@context': 'https://www.w3.org/ns/activitystreams',
-          id: "https://#{valid_domain}/@foo/1234/create",
+          id: "https://foo.bar/@foo/1234/create",
           type: 'Create',
           actor: ActivityPub::TagManager.instance.uri_for(sender),
           object: note,
@@ -174,7 +174,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
       let(:object) do
         {
           '@context': 'https://www.w3.org/ns/activitystreams',
-          id: "https://#{valid_domain}/@foo/1234/create",
+          id: "https://foo.bar/@foo/1234/create",
           type: 'Create',
           actor: ActivityPub::TagManager.instance.uri_for(sender),
           object: {
@@ -208,7 +208,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
         let(:object) do
           {
             '@context': 'https://www.w3.org/ns/activitystreams',
-            id: "https://#{valid_domain}/@foo/1234/create",
+            id: "https://foo.bar/@foo/1234/create",
             type: 'Create',
             actor: ActivityPub::TagManager.instance.uri_for(sender),
             object: note.merge(updated: '2021-09-08T22:39:25Z'),
diff --git a/spec/services/fetch_remote_status_service_spec.rb b/spec/services/fetch_remote_status_service_spec.rb
index 0e63cc9eb..fe5f1aed1 100644
--- a/spec/services/fetch_remote_status_service_spec.rb
+++ b/spec/services/fetch_remote_status_service_spec.rb
@@ -1,14 +1,13 @@
 require 'rails_helper'
 
 RSpec.describe FetchRemoteStatusService, type: :service do
-  let(:account) { Fabricate(:account) }
+  let(:account) { Fabricate(:account, domain: 'example.org', uri: 'https://example.org/foo') }
   let(:prefetched_body) { nil }
-  let(:valid_domain) { Rails.configuration.x.local_domain }
 
   let(:note) do
     {
       '@context': 'https://www.w3.org/ns/activitystreams',
-      id: "https://#{valid_domain}/@foo/1234",
+      id: "https://example.org/@foo/1234",
       type: 'Note',
       content: 'Lorem ipsum',
       attributedTo: ActivityPub::TagManager.instance.uri_for(account),
@@ -20,7 +19,6 @@ RSpec.describe FetchRemoteStatusService, type: :service do
     let(:prefetched_body) { Oj.dump(note) }
 
     before do
-      account.update(uri: ActivityPub::TagManager.instance.uri_for(account))
       subject
     end
 
diff --git a/spec/services/resolve_url_service_spec.rb b/spec/services/resolve_url_service_spec.rb
index 1b639dea9..b3e3defbf 100644
--- a/spec/services/resolve_url_service_spec.rb
+++ b/spec/services/resolve_url_service_spec.rb
@@ -126,5 +126,24 @@ describe ResolveURLService, type: :service do
         end
       end
     end
+
+    context 'searching for a link that redirects to a local public status' do
+      let(:account) { Fabricate(:account) }
+      let(:poster)  { Fabricate(:account) }
+      let!(:status) { Fabricate(:status, account: poster, visibility: :public) }
+      let(:url)     { 'https://link.to/foobar' }
+      let(:status_url) { ActivityPub::TagManager.instance.url_for(status) }
+      let(:uri)     { ActivityPub::TagManager.instance.uri_for(status) }
+
+      before do
+        stub_request(:get, url).to_return(status: 302, headers: { 'Location' => status_url })
+        body = ActiveModelSerializers::SerializableResource.new(status, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter).to_json
+        stub_request(:get, status_url).to_return(body: body, headers: { 'Content-Type' => 'application/activity+json' })
+      end
+
+      it 'returns status by url' do
+        expect(subject.call(url, on_behalf_of: account)).to eq(status)
+      end
+    end
   end
 end