Merge commit '55e7c08a83547424024bac311d5459cb82cf6dae' into glitch-soc/merge-upstream
Conflicts: - `app/models/user_settings.rb`: Upstream added a constraint on a setting textually close to glitch-soc-only settings. Applied upstream's change. - `lib/sanitize_ext/sanitize_config.rb`: Upstream added support for the `translate` attribute on a few elements, where glitch-soc had a different set of allowed elements and attributes. Extended glitch-soc's allowed attributes with `translate` as upstream did. - `spec/validators/status_length_validator_spec.rb`: Upstream refactored to use RSpec's `instance_double` instead of `double`, but glitch-soc had changes to tests due to configurable max toot chars. Applied upstream's changes while keeping tests against configurable max toot chars.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -62,17 +62,10 @@ describe Admin::Reports::ActionsController do
|
||||
end
|
||||
|
||||
shared_examples 'common behavior' do
|
||||
it 'closes the report' do
|
||||
expect { subject }.to change { report.reload.action_taken? }.from(false).to(true)
|
||||
end
|
||||
it 'closes the report and redirects' do
|
||||
expect { subject }.to mark_report_action_taken.and create_target_account_strike
|
||||
|
||||
it 'creates a strike with the expected text' do
|
||||
expect { subject }.to change { report.target_account.strikes.count }.by(1)
|
||||
expect(report.target_account.strikes.last.text).to eq text
|
||||
end
|
||||
|
||||
it 'redirects' do
|
||||
subject
|
||||
expect(response).to redirect_to(admin_reports_path)
|
||||
end
|
||||
|
||||
@@ -81,20 +74,21 @@ describe Admin::Reports::ActionsController do
|
||||
{ report_id: report.id }
|
||||
end
|
||||
|
||||
it 'closes the report' do
|
||||
expect { subject }.to change { report.reload.action_taken? }.from(false).to(true)
|
||||
end
|
||||
it 'closes the report and redirects' do
|
||||
expect { subject }.to mark_report_action_taken.and create_target_account_strike
|
||||
|
||||
it 'creates a strike with the expected text' do
|
||||
expect { subject }.to change { report.target_account.strikes.count }.by(1)
|
||||
expect(report.target_account.strikes.last.text).to eq ''
|
||||
end
|
||||
|
||||
it 'redirects' do
|
||||
subject
|
||||
expect(response).to redirect_to(admin_reports_path)
|
||||
end
|
||||
end
|
||||
|
||||
def mark_report_action_taken
|
||||
change { report.reload.action_taken? }.from(false).to(true)
|
||||
end
|
||||
|
||||
def create_target_account_strike
|
||||
change { report.target_account.strikes.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'all action types' do
|
||||
|
||||
@@ -48,7 +48,7 @@ describe Admin::WebhooksController do
|
||||
end
|
||||
|
||||
context 'with an existing record' do
|
||||
let!(:webhook) { Fabricate :webhook }
|
||||
let!(:webhook) { Fabricate(:webhook, events: ['account.created', 'report.created']) }
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success and renders view' do
|
||||
@@ -82,7 +82,7 @@ describe Admin::WebhooksController do
|
||||
end.to_not change(webhook, :url)
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response).to render_template(:show)
|
||||
expect(response).to render_template(:edit)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::Admin::AccountActionsController do
|
||||
render_views
|
||||
|
||||
let(:role) { UserRole.find_by(name: 'Moderator') }
|
||||
let(:user) { Fabricate(:user, role: role) }
|
||||
let(:scopes) { 'admin:read admin:write' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
context 'with type of disable' do
|
||||
before do
|
||||
post :create, params: { account_id: account.id, type: 'disable' }
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||
it_behaves_like 'forbidden for wrong role', ''
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'performs action against account' do
|
||||
expect(account.reload.user_disabled?).to be true
|
||||
end
|
||||
|
||||
it 'logs action' do
|
||||
log_item = Admin::ActionLog.last
|
||||
|
||||
expect(log_item).to_not be_nil
|
||||
expect(log_item.action).to eq :disable
|
||||
expect(log_item.account_id).to eq user.account_id
|
||||
expect(log_item.target_id).to eq account.user.id
|
||||
end
|
||||
end
|
||||
|
||||
context 'with no type' do
|
||||
before do
|
||||
post :create, params: { account_id: account.id }
|
||||
end
|
||||
|
||||
it 'returns http unprocessable entity' do
|
||||
expect(response).to have_http_status(422)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -18,6 +18,7 @@ RSpec.describe Api::V1::ConversationsController do
|
||||
|
||||
before do
|
||||
PostStatusService.new.call(other.account, text: 'Hey @alice', visibility: 'direct')
|
||||
PostStatusService.new.call(user.account, text: 'Hey, nobody here', visibility: 'direct')
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
@@ -33,7 +34,8 @@ RSpec.describe Api::V1::ConversationsController do
|
||||
it 'returns conversations' do
|
||||
get :index
|
||||
json = body_as_json
|
||||
expect(json.size).to eq 1
|
||||
expect(json.size).to eq 2
|
||||
expect(json[0][:accounts].size).to eq 1
|
||||
end
|
||||
|
||||
context 'with since_id' do
|
||||
@@ -41,7 +43,7 @@ RSpec.describe Api::V1::ConversationsController do
|
||||
it 'returns conversations' do
|
||||
get :index, params: { since_id: Mastodon::Snowflake.id_at(1.hour.ago, with_random: false) }
|
||||
json = body_as_json
|
||||
expect(json.size).to eq 1
|
||||
expect(json.size).to eq 2
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -67,24 +67,13 @@ RSpec.describe Api::V1::NotificationsController do
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
it 'returns expected notification types', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'includes reblog' do
|
||||
expect(body_as_json.pluck(:type)).to include 'reblog'
|
||||
end
|
||||
|
||||
it 'includes mention' do
|
||||
expect(body_as_json.pluck(:type)).to include 'mention'
|
||||
end
|
||||
|
||||
it 'includes favourite' do
|
||||
expect(body_as_json.pluck(:type)).to include 'favourite'
|
||||
end
|
||||
|
||||
it 'includes follow' do
|
||||
expect(body_as_json.pluck(:type)).to include 'follow'
|
||||
expect(body_json_types).to include 'reblog'
|
||||
expect(body_json_types).to include 'mention'
|
||||
expect(body_json_types).to include 'favourite'
|
||||
expect(body_json_types).to include 'follow'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -93,12 +82,14 @@ RSpec.describe Api::V1::NotificationsController do
|
||||
get :index, params: { account_id: third.account.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
it 'returns only notifications from specified user', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
|
||||
expect(body_json_account_ids.uniq).to eq [third.account.id.to_s]
|
||||
end
|
||||
|
||||
it 'returns only notifications from specified user' do
|
||||
expect(body_as_json.map { |x| x[:account][:id] }.uniq).to eq [third.account.id.to_s]
|
||||
def body_json_account_ids
|
||||
body_as_json.map { |x| x[:account][:id] }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -107,27 +98,23 @@ RSpec.describe Api::V1::NotificationsController do
|
||||
get :index, params: { account_id: 'foo' }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
it 'returns nothing', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns nothing' do
|
||||
expect(body_as_json.size).to eq 0
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with excluded_types param' do
|
||||
describe 'with exclude_types param' do
|
||||
before do
|
||||
get :index, params: { exclude_types: %w(mention) }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
it 'returns everything but excluded type', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns everything but excluded type' do
|
||||
expect(body_as_json.size).to_not eq 0
|
||||
expect(body_as_json.pluck(:type).uniq).to_not include 'mention'
|
||||
expect(body_json_types.uniq).to_not include 'mention'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -136,13 +123,15 @@ RSpec.describe Api::V1::NotificationsController do
|
||||
get :index, params: { types: %w(mention) }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
it 'returns only requested type', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns only requested type' do
|
||||
expect(body_as_json.pluck(:type).uniq).to eq ['mention']
|
||||
expect(body_json_types.uniq).to eq ['mention']
|
||||
end
|
||||
end
|
||||
|
||||
def body_json_types
|
||||
body_as_json.pluck(:type)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ describe Api::V1::Statuses::HistoriesController do
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json.size).to_not be 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::SuggestionsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read write') }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
let(:bob) { Fabricate(:account) }
|
||||
let(:jeff) { Fabricate(:account) }
|
||||
|
||||
before do
|
||||
PotentialFriendshipTracker.record(user.account_id, bob.id, :reblog)
|
||||
PotentialFriendshipTracker.record(user.account_id, jeff.id, :favourite)
|
||||
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns accounts' do
|
||||
json = body_as_json
|
||||
|
||||
expect(json.size).to be >= 1
|
||||
expect(json.pluck(:id)).to include(*[bob, jeff].map { |i| i.id.to_s })
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,88 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::TagsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:scopes) { 'write:follows' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
|
||||
before { allow(controller).to receive(:doorkeeper_token) { token } }
|
||||
|
||||
describe 'GET #show' do
|
||||
before do
|
||||
get :show, params: { id: name }
|
||||
end
|
||||
|
||||
context 'with existing tag' do
|
||||
let!(:tag) { Fabricate(:tag) }
|
||||
let(:name) { tag.name }
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with non-existing tag' do
|
||||
let(:name) { 'hoge' }
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #follow' do
|
||||
let!(:unrelated_tag) { Fabricate(:tag) }
|
||||
|
||||
before do
|
||||
TagFollow.create!(account: user.account, tag: unrelated_tag)
|
||||
|
||||
post :follow, params: { id: name }
|
||||
end
|
||||
|
||||
context 'with existing tag' do
|
||||
let!(:tag) { Fabricate(:tag) }
|
||||
let(:name) { tag.name }
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
|
||||
it 'creates follow' do
|
||||
expect(TagFollow.where(tag: tag, account: user.account).exists?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'with non-existing tag' do
|
||||
let(:name) { 'hoge' }
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
|
||||
it 'creates follow' do
|
||||
expect(TagFollow.where(tag: Tag.find_by!(name: name), account: user.account).exists?).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #unfollow' do
|
||||
let!(:tag) { Fabricate(:tag, name: 'foo') }
|
||||
let!(:tag_follow) { Fabricate(:tag_follow, account: user.account, tag: tag) }
|
||||
|
||||
before do
|
||||
post :unfollow, params: { id: tag.name }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
|
||||
it 'removes the follow' do
|
||||
expect(TagFollow.where(tag: tag, account: user.account).exists?).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -55,5 +55,13 @@ RSpec.describe Api::V2::Admin::AccountsController do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with limit param' do
|
||||
let(:params) { { limit: 1 } }
|
||||
|
||||
it 'sets the correct pagination headers' do
|
||||
expect(response.headers['Link'].find_link(%w(rel next)).href).to eq api_v2_admin_accounts_url(limit: 1, max_id: admin_account.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -75,23 +75,11 @@ describe StatusesController do
|
||||
context 'with HTML' do
|
||||
let(:format) { 'html' }
|
||||
|
||||
it 'returns http success' do
|
||||
it 'renders status successfully', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns public Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'public'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
expect(response).to render_template(:show)
|
||||
expect(response.body).to include status.text
|
||||
end
|
||||
@@ -100,25 +88,13 @@ describe StatusesController do
|
||||
context 'with JSON' do
|
||||
let(:format) { 'json' }
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it_behaves_like 'cacheable response'
|
||||
|
||||
it 'returns Content-Type header' do
|
||||
it 'renders ActivityPub Note object successfully', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
expect(response.headers['Content-Type']).to include 'application/activity+json'
|
||||
end
|
||||
|
||||
it 'renders ActivityPub Note object' do
|
||||
json = body_as_json
|
||||
expect(json[:content]).to include status.text
|
||||
end
|
||||
@@ -199,23 +175,11 @@ describe StatusesController do
|
||||
context 'with HTML' do
|
||||
let(:format) { 'html' }
|
||||
|
||||
it 'returns http success' do
|
||||
it 'renders status successfully', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
expect(response).to render_template(:show)
|
||||
expect(response.body).to include status.text
|
||||
end
|
||||
@@ -224,27 +188,12 @@ describe StatusesController do
|
||||
context 'with JSON' do
|
||||
let(:format) { 'json' }
|
||||
|
||||
it 'returns http success' do
|
||||
it 'renders ActivityPub Note object successfully', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'returns Content-Type header' do
|
||||
expect(response.headers['Content-Type']).to include 'application/activity+json'
|
||||
end
|
||||
|
||||
it 'renders ActivityPub Note object' do
|
||||
json = body_as_json
|
||||
expect(json[:content]).to include status.text
|
||||
end
|
||||
@@ -263,23 +212,11 @@ describe StatusesController do
|
||||
context 'with HTML' do
|
||||
let(:format) { 'html' }
|
||||
|
||||
it 'returns http success' do
|
||||
it 'renders status successfully', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
expect(response).to render_template(:show)
|
||||
expect(response.body).to include status.text
|
||||
end
|
||||
@@ -288,27 +225,12 @@ describe StatusesController do
|
||||
context 'with JSON' do
|
||||
let(:format) { 'json' }
|
||||
|
||||
it 'returns http success' do
|
||||
it 'renders ActivityPub Note object successfully', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'returns Content-Type header' do
|
||||
expect(response.headers['Content-Type']).to include 'application/activity+json'
|
||||
end
|
||||
|
||||
it 'renders ActivityPub Note object' do
|
||||
json = body_as_json
|
||||
expect(json[:content]).to include status.text
|
||||
end
|
||||
@@ -350,23 +272,11 @@ describe StatusesController do
|
||||
context 'with HTML' do
|
||||
let(:format) { 'html' }
|
||||
|
||||
it 'returns http success' do
|
||||
it 'renders status successfully', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
expect(response).to render_template(:show)
|
||||
expect(response.body).to include status.text
|
||||
end
|
||||
@@ -375,27 +285,12 @@ describe StatusesController do
|
||||
context 'with JSON' do
|
||||
let(:format) { 'json' }
|
||||
|
||||
it 'returns http success' do
|
||||
it 'renders ActivityPub Note object successfully' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'returns Content-Type header' do
|
||||
expect(response.headers['Content-Type']).to include 'application/activity+json'
|
||||
end
|
||||
|
||||
it 'renders ActivityPub Note object' do
|
||||
json = body_as_json
|
||||
expect(json[:content]).to include status.text
|
||||
end
|
||||
@@ -463,23 +358,11 @@ describe StatusesController do
|
||||
context 'with HTML' do
|
||||
let(:format) { 'html' }
|
||||
|
||||
it 'returns http success' do
|
||||
it 'renders status successfully', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
expect(response).to render_template(:show)
|
||||
expect(response.body).to include status.text
|
||||
end
|
||||
@@ -488,25 +371,13 @@ describe StatusesController do
|
||||
context 'with JSON' do
|
||||
let(:format) { 'json' }
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it_behaves_like 'cacheable response'
|
||||
|
||||
it 'returns Content-Type header' do
|
||||
it 'renders ActivityPub Note object successfully', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
expect(response.headers['Content-Type']).to include 'application/activity+json'
|
||||
end
|
||||
|
||||
it 'renders ActivityPub Note object' do
|
||||
json = body_as_json
|
||||
expect(json[:content]).to include status.text
|
||||
end
|
||||
@@ -525,23 +396,11 @@ describe StatusesController do
|
||||
context 'with HTML' do
|
||||
let(:format) { 'html' }
|
||||
|
||||
it 'returns http success' do
|
||||
it 'renders status successfully', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
expect(response).to render_template(:show)
|
||||
expect(response.body).to include status.text
|
||||
end
|
||||
@@ -550,27 +409,12 @@ describe StatusesController do
|
||||
context 'with JSON' do
|
||||
let(:format) { 'json' }
|
||||
|
||||
it 'returns http success' do
|
||||
it 'renders ActivityPub Note object successfully' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'returns Content-Type header' do
|
||||
expect(response.headers['Content-Type']).to include 'application/activity+json'
|
||||
end
|
||||
|
||||
it 'renders ActivityPub Note object' do
|
||||
json = body_as_json
|
||||
expect(json[:content]).to include status.text
|
||||
end
|
||||
@@ -612,23 +456,11 @@ describe StatusesController do
|
||||
context 'with HTML' do
|
||||
let(:format) { 'html' }
|
||||
|
||||
it 'returns http success' do
|
||||
it 'renders status successfully', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
expect(response).to render_template(:show)
|
||||
expect(response.body).to include status.text
|
||||
end
|
||||
@@ -637,27 +469,12 @@ describe StatusesController do
|
||||
context 'with JSON' do
|
||||
let(:format) { 'json' }
|
||||
|
||||
it 'returns http success' do
|
||||
it 'renders ActivityPub Note object', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'returns Content-Type header' do
|
||||
expect(response.headers['Content-Type']).to include 'application/activity+json'
|
||||
end
|
||||
|
||||
it 'renders ActivityPub Note object' do
|
||||
json = body_as_json
|
||||
expect(json[:content]).to include status.text
|
||||
end
|
||||
@@ -933,23 +750,11 @@ describe StatusesController do
|
||||
get :embed, params: { account_username: status.account.username, id: status.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
it 'renders status successfully', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Link header' do
|
||||
expect(response.headers['Link'].to_s).to include 'activity+json'
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns public Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'public'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
expect(response).to render_template(:embed)
|
||||
expect(response.body).to include status.text
|
||||
end
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -48,16 +48,25 @@ describe RequestPool do
|
||||
expect(subject.size).to be > 1
|
||||
end
|
||||
|
||||
it 'closes idle connections' do
|
||||
stub_request(:get, 'http://example.com/').to_return(status: 200, body: 'Hello!')
|
||||
|
||||
subject.with('http://example.com') do |http_client|
|
||||
http_client.get('/').flush
|
||||
context 'with an idle connection' do
|
||||
before do
|
||||
stub_const('RequestPool::MAX_IDLE_TIME', 1) # Lower idle time limit to 1 seconds
|
||||
stub_const('RequestPool::REAPER_FREQUENCY', 0.1) # Run reaper every 0.1 seconds
|
||||
stub_request(:get, 'http://example.com/').to_return(status: 200, body: 'Hello!')
|
||||
end
|
||||
|
||||
expect(subject.size).to eq 1
|
||||
sleep RequestPool::MAX_IDLE_TIME + 30 + 1
|
||||
expect(subject.size).to eq 0
|
||||
it 'closes the connections' do
|
||||
subject.with('http://example.com') do |http_client|
|
||||
http_client.get('/').flush
|
||||
end
|
||||
|
||||
expect { reaper_observes_idle_timeout }.to change(subject, :size).from(1).to(0)
|
||||
end
|
||||
|
||||
def reaper_observes_idle_timeout
|
||||
# One full idle period and 2 reaper cycles more
|
||||
sleep RequestPool::MAX_IDLE_TIME + (RequestPool::REAPER_FREQUENCY * 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -36,6 +36,14 @@ describe Sanitize::Config do
|
||||
expect(Sanitize.fragment('<a href="http://example.com">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener noreferrer" target="_blank">Test</a>'
|
||||
end
|
||||
|
||||
it 'keeps a with translate="no"' do
|
||||
expect(Sanitize.fragment('<a href="http://example.com" translate="no">Test</a>', subject)).to eq '<a href="http://example.com" translate="no" rel="nofollow noopener noreferrer" target="_blank">Test</a>'
|
||||
end
|
||||
|
||||
it 'removes "translate" attribute with invalid value' do
|
||||
expect(Sanitize.fragment('<a href="http://example.com" translate="foo">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener noreferrer" target="_blank">Test</a>'
|
||||
end
|
||||
|
||||
it 'removes a with unparsable href' do
|
||||
expect(Sanitize.fragment('<a href=" https://google.fr">Test</a>', subject)).to eq 'Test'
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -142,4 +142,59 @@ describe UserMailer do
|
||||
expect(mail.body.encoded).to include I18n.t('user_mailer.appeal_rejected.title')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'two_factor_enabled' do
|
||||
let(:mail) { described_class.two_factor_enabled(receiver) }
|
||||
|
||||
it 'renders two_factor_enabled mail' do
|
||||
expect(mail.subject).to eq I18n.t('devise.mailer.two_factor_enabled.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.two_factor_enabled.explanation')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'two_factor_disabled' do
|
||||
let(:mail) { described_class.two_factor_disabled(receiver) }
|
||||
|
||||
it 'renders two_factor_disabled mail' do
|
||||
expect(mail.subject).to eq I18n.t('devise.mailer.two_factor_disabled.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.two_factor_disabled.explanation')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'webauthn_enabled' do
|
||||
let(:mail) { described_class.webauthn_enabled(receiver) }
|
||||
|
||||
it 'renders webauthn_enabled mail' do
|
||||
expect(mail.subject).to eq I18n.t('devise.mailer.webauthn_enabled.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.webauthn_enabled.explanation')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'webauthn_disabled' do
|
||||
let(:mail) { described_class.webauthn_disabled(receiver) }
|
||||
|
||||
it 'renders webauthn_disabled mail' do
|
||||
expect(mail.subject).to eq I18n.t('devise.mailer.webauthn_disabled.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.webauthn_disabled.explanation')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'two_factor_recovery_codes_changed' do
|
||||
let(:mail) { described_class.two_factor_recovery_codes_changed(receiver) }
|
||||
|
||||
it 'renders two_factor_recovery_codes_changed mail' do
|
||||
expect(mail.subject).to eq I18n.t('devise.mailer.two_factor_recovery_codes_changed.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.two_factor_recovery_codes_changed.explanation')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'webauthn_credential_added' do
|
||||
let(:credential) { Fabricate.build(:webauthn_credential) }
|
||||
let(:mail) { described_class.webauthn_credential_added(receiver, credential) }
|
||||
|
||||
it 'renders webauthn_credential_added mail' do
|
||||
expect(mail.subject).to eq I18n.t('devise.mailer.webauthn_credential.added.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.webauthn_credential.added.explanation')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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' } }
|
||||
|
||||
@@ -49,6 +49,16 @@ RSpec.describe UserSettings do
|
||||
expect(subject[:always_send_emails]).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the setting has a closed set of values' do
|
||||
it 'updates the attribute when given a valid value' do
|
||||
expect { subject[:'web.display_media'] = :show_all }.to change { subject[:'web.display_media'] }.from('default').to('show_all')
|
||||
end
|
||||
|
||||
it 'raises an error when given an invalid value' do
|
||||
expect { subject[:'web.display_media'] = 'invalid value' }.to raise_error ArgumentError
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#update' do
|
||||
|
||||
@@ -8,16 +8,32 @@ describe WebhookPolicy do
|
||||
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
|
||||
let(:john) { Fabricate(:account) }
|
||||
|
||||
permissions :index?, :create?, :show?, :update?, :enable?, :disable?, :rotate_secret?, :destroy? do
|
||||
permissions :index?, :create? do
|
||||
context 'with an admin' do
|
||||
it 'permits' do
|
||||
expect(policy).to permit(admin, Tag)
|
||||
expect(policy).to permit(admin, Webhook)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a non-admin' do
|
||||
it 'denies' do
|
||||
expect(policy).to_not permit(john, Tag)
|
||||
expect(policy).to_not permit(john, Webhook)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
permissions :show?, :update?, :enable?, :disable?, :rotate_secret?, :destroy? do
|
||||
let(:webhook) { Fabricate(:webhook, events: ['account.created', 'report.created']) }
|
||||
|
||||
context 'with an admin' do
|
||||
it 'permits' do
|
||||
expect(policy).to permit(admin, webhook)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a non-admin' do
|
||||
it 'denies' do
|
||||
expect(policy).to_not permit(john, webhook)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Account actions' do
|
||||
let(:role) { UserRole.find_by(name: 'Admin') }
|
||||
let(:user) { Fabricate(:user, role: role) }
|
||||
let(:scopes) { 'admin:write admin:write:accounts' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:mailer) { instance_double(ActionMailer::MessageDelivery, deliver_later!: nil) }
|
||||
|
||||
before do
|
||||
allow(UserMailer).to receive(:warning).with(target_account.user, anything).and_return(mailer)
|
||||
end
|
||||
|
||||
shared_examples 'a successful notification delivery' do
|
||||
it 'notifies the user about the action taken' do
|
||||
subject
|
||||
|
||||
expect(UserMailer).to have_received(:warning).with(target_account.user, anything).once
|
||||
expect(mailer).to have_received(:deliver_later!).once
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'a successful logged action' do |action_type, target_type|
|
||||
it 'logs action' do
|
||||
subject
|
||||
|
||||
log_item = Admin::ActionLog.last
|
||||
|
||||
expect(log_item).to be_present
|
||||
expect(log_item.action).to eq(action_type)
|
||||
expect(log_item.account_id).to eq(user.account_id)
|
||||
expect(log_item.target_id).to eq(target_type == :user ? target_account.user.id : target_account.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/admin/accounts/:id/action' do
|
||||
subject do
|
||||
post "/api/v1/admin/accounts/#{target_account.id}/action", headers: headers, params: params
|
||||
end
|
||||
|
||||
let(:target_account) { Fabricate(:account) }
|
||||
|
||||
context 'with type of disable' do
|
||||
let(:params) { { type: 'disable' } }
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'admin:read admin:read:accounts'
|
||||
it_behaves_like 'forbidden for wrong role', ''
|
||||
it_behaves_like 'a successful notification delivery'
|
||||
it_behaves_like 'a successful logged action', :disable, :user
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'disables the target account' do
|
||||
expect { subject }.to change { target_account.reload.user_disabled? }.from(false).to(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with type of sensitive' do
|
||||
let(:params) { { type: 'sensitive' } }
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'admin:read admin:read:accounts'
|
||||
it_behaves_like 'forbidden for wrong role', ''
|
||||
it_behaves_like 'a successful notification delivery'
|
||||
it_behaves_like 'a successful logged action', :sensitive, :account
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'marks the target account as sensitive' do
|
||||
expect { subject }.to change { target_account.reload.sensitized? }.from(false).to(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with type of silence' do
|
||||
let(:params) { { type: 'silence' } }
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'admin:read admin:read:accounts'
|
||||
it_behaves_like 'forbidden for wrong role', ''
|
||||
it_behaves_like 'a successful notification delivery'
|
||||
it_behaves_like 'a successful logged action', :silence, :account
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'marks the target account as silenced' do
|
||||
expect { subject }.to change { target_account.reload.silenced? }.from(false).to(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with type of suspend' do
|
||||
let(:params) { { type: 'suspend' } }
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'admin:read admin:read:accounts'
|
||||
it_behaves_like 'forbidden for wrong role', ''
|
||||
it_behaves_like 'a successful notification delivery'
|
||||
it_behaves_like 'a successful logged action', :suspend, :account
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'marks the target account as suspended' do
|
||||
expect { subject }.to change { target_account.reload.suspended? }.from(false).to(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with type of none' do
|
||||
let(:params) { { type: 'none' } }
|
||||
|
||||
it_behaves_like 'a successful notification delivery'
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with no type' do
|
||||
let(:params) { {} }
|
||||
|
||||
it 'returns http unprocessable entity' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with invalid type' do
|
||||
let(:params) { { type: 'invalid' } }
|
||||
|
||||
it 'returns http unprocessable entity' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,103 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Suggestions' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'read' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
|
||||
describe 'GET /api/v1/suggestions' do
|
||||
subject do
|
||||
get '/api/v1/suggestions', headers: headers, params: params
|
||||
end
|
||||
|
||||
let(:bob) { Fabricate(:account) }
|
||||
let(:jeff) { Fabricate(:account) }
|
||||
let(:params) { {} }
|
||||
|
||||
before do
|
||||
PotentialFriendshipTracker.record(user.account_id, bob.id, :reblog)
|
||||
PotentialFriendshipTracker.record(user.account_id, jeff.id, :favourite)
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'write'
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns accounts' do
|
||||
subject
|
||||
|
||||
body = body_as_json
|
||||
|
||||
expect(body.size).to eq 2
|
||||
expect(body.pluck(:id)).to match_array([bob, jeff].map { |i| i.id.to_s })
|
||||
end
|
||||
|
||||
context 'with limit param' do
|
||||
let(:params) { { limit: 1 } }
|
||||
|
||||
it 'returns only the requested number of accounts' do
|
||||
subject
|
||||
|
||||
expect(body_as_json.size).to eq 1
|
||||
end
|
||||
end
|
||||
|
||||
context 'without an authorization header' do
|
||||
let(:headers) { {} }
|
||||
|
||||
it 'returns http unauthorized' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(401)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /api/v1/suggestions/:id' do
|
||||
subject do
|
||||
delete "/api/v1/suggestions/#{jeff.id}", headers: headers
|
||||
end
|
||||
|
||||
let(:suggestions_source) { instance_double(AccountSuggestions::PastInteractionsSource, remove: nil) }
|
||||
let(:bob) { Fabricate(:account) }
|
||||
let(:jeff) { Fabricate(:account) }
|
||||
|
||||
before do
|
||||
PotentialFriendshipTracker.record(user.account_id, bob.id, :reblog)
|
||||
PotentialFriendshipTracker.record(user.account_id, jeff.id, :favourite)
|
||||
allow(AccountSuggestions::PastInteractionsSource).to receive(:new).and_return(suggestions_source)
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'write'
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'removes the specified suggestion' do
|
||||
subject
|
||||
|
||||
expect(suggestions_source).to have_received(:remove).with(user.account, jeff.id.to_s).once
|
||||
expect(suggestions_source).to_not have_received(:remove).with(user.account, bob.id.to_s)
|
||||
end
|
||||
|
||||
context 'without an authorization header' do
|
||||
let(:headers) { {} }
|
||||
|
||||
it 'returns http unauthorized' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(401)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,169 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Tags' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:scopes) { 'write:follows' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
|
||||
describe 'GET /api/v1/tags/:id' do
|
||||
subject do
|
||||
get "/api/v1/tags/#{name}"
|
||||
end
|
||||
|
||||
context 'when the tag exists' do
|
||||
let!(:tag) { Fabricate(:tag) }
|
||||
let(:name) { tag.name }
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns the tag' do
|
||||
subject
|
||||
|
||||
expect(body_as_json[:name]).to eq(name)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the tag does not exist' do
|
||||
let(:name) { 'hoge' }
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the tag name is invalid' do
|
||||
let(:name) { 'tag-name' }
|
||||
|
||||
it 'returns http not found' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/tags/:id/follow' do
|
||||
subject do
|
||||
post "/api/v1/tags/#{name}/follow", headers: headers
|
||||
end
|
||||
|
||||
let!(:tag) { Fabricate(:tag) }
|
||||
let(:name) { tag.name }
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read read:follows'
|
||||
|
||||
context 'when the tag exists' do
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
|
||||
it 'creates follow' do
|
||||
subject
|
||||
|
||||
expect(TagFollow.where(tag: tag, account: user.account)).to exist
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the tag does not exist' do
|
||||
let(:name) { 'hoge' }
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'creates a new tag with the specified name' do
|
||||
subject
|
||||
|
||||
expect(Tag.where(name: name)).to exist
|
||||
end
|
||||
|
||||
it 'creates follow' do
|
||||
subject
|
||||
|
||||
expect(TagFollow.where(tag: Tag.find_by(name: name), account: user.account)).to exist
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the tag name is invalid' do
|
||||
let(:name) { 'tag-name' }
|
||||
|
||||
it 'returns http not found' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the Authorization header is missing' do
|
||||
let(:headers) { {} }
|
||||
let(:name) { 'unauthorized' }
|
||||
|
||||
it 'returns http unauthorized' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(401)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #unfollow' do
|
||||
subject do
|
||||
post "/api/v1/tags/#{name}/unfollow", headers: headers
|
||||
end
|
||||
|
||||
let(:name) { tag.name }
|
||||
let!(:tag) { Fabricate(:tag, name: 'foo') }
|
||||
|
||||
before do
|
||||
Fabricate(:tag_follow, account: user.account, tag: tag)
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read read:follows'
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'removes the follow' do
|
||||
subject
|
||||
|
||||
expect(TagFollow.where(tag: tag, account: user.account)).to_not exist
|
||||
end
|
||||
|
||||
context 'when the tag name is invalid' do
|
||||
let(:name) { 'tag-name' }
|
||||
|
||||
it 'returns http not found' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the Authorization header is missing' do
|
||||
let(:headers) { {} }
|
||||
let(:name) { 'unauthorized' }
|
||||
|
||||
it 'returns http unauthorized' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(401)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -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)
|
||||
|
||||
@@ -30,7 +30,7 @@ RSpec.describe BackupService, type: :service do
|
||||
it 'stores them as expected' do
|
||||
service_call
|
||||
|
||||
json = Oj.load(read_zip_file(backup, 'actor.json'))
|
||||
json = export_json(:actor)
|
||||
avatar_path = json.dig('icon', 'url')
|
||||
header_path = json.dig('image', 'url')
|
||||
|
||||
@@ -42,47 +42,60 @@ RSpec.describe BackupService, type: :service do
|
||||
end
|
||||
end
|
||||
|
||||
it 'marks the backup as processed' do
|
||||
expect { service_call }.to change(backup, :processed).from(false).to(true)
|
||||
it 'marks the backup as processed and exports files' do
|
||||
expect { service_call }.to process_backup
|
||||
|
||||
expect_outbox_export
|
||||
expect_likes_export
|
||||
expect_bookmarks_export
|
||||
end
|
||||
|
||||
it 'exports outbox.json as expected' do
|
||||
service_call
|
||||
def process_backup
|
||||
change(backup, :processed).from(false).to(true)
|
||||
end
|
||||
|
||||
json = Oj.load(read_zip_file(backup, 'outbox.json'))
|
||||
expect(json['@context']).to_not be_nil
|
||||
expect(json['type']).to eq 'OrderedCollection'
|
||||
expect(json['totalItems']).to eq 2
|
||||
expect(json['orderedItems'][0]['@context']).to be_nil
|
||||
expect(json['orderedItems'][0]).to include({
|
||||
def expect_outbox_export
|
||||
json = export_json(:outbox)
|
||||
|
||||
aggregate_failures do
|
||||
expect(json['@context']).to_not be_nil
|
||||
expect(json['type']).to eq 'OrderedCollection'
|
||||
expect(json['totalItems']).to eq 2
|
||||
expect(json['orderedItems'][0]['@context']).to be_nil
|
||||
expect(json['orderedItems'][0]).to include_create_item(status)
|
||||
expect(json['orderedItems'][1]).to include_create_item(private_status)
|
||||
end
|
||||
end
|
||||
|
||||
def expect_likes_export
|
||||
json = export_json(:likes)
|
||||
|
||||
aggregate_failures do
|
||||
expect(json['type']).to eq 'OrderedCollection'
|
||||
expect(json['orderedItems']).to eq [ActivityPub::TagManager.instance.uri_for(favourite.status)]
|
||||
end
|
||||
end
|
||||
|
||||
def expect_bookmarks_export
|
||||
json = export_json(:bookmarks)
|
||||
|
||||
aggregate_failures do
|
||||
expect(json['type']).to eq 'OrderedCollection'
|
||||
expect(json['orderedItems']).to eq [ActivityPub::TagManager.instance.uri_for(bookmark.status)]
|
||||
end
|
||||
end
|
||||
|
||||
def export_json(type)
|
||||
Oj.load(read_zip_file(backup, "#{type}.json"))
|
||||
end
|
||||
|
||||
def include_create_item(status)
|
||||
include({
|
||||
'type' => 'Create',
|
||||
'object' => include({
|
||||
'id' => ActivityPub::TagManager.instance.uri_for(status),
|
||||
'content' => '<p>Hello</p>',
|
||||
'content' => "<p>#{status.text}</p>",
|
||||
}),
|
||||
})
|
||||
expect(json['orderedItems'][1]).to include({
|
||||
'type' => 'Create',
|
||||
'object' => include({
|
||||
'id' => ActivityPub::TagManager.instance.uri_for(private_status),
|
||||
'content' => '<p>secret</p>',
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
it 'exports likes.json as expected' do
|
||||
service_call
|
||||
|
||||
json = Oj.load(read_zip_file(backup, 'likes.json'))
|
||||
expect(json['type']).to eq 'OrderedCollection'
|
||||
expect(json['orderedItems']).to eq [ActivityPub::TagManager.instance.uri_for(favourite.status)]
|
||||
end
|
||||
|
||||
it 'exports bookmarks.json as expected' do
|
||||
service_call
|
||||
|
||||
json = Oj.load(read_zip_file(backup, 'bookmarks.json'))
|
||||
expect(json['type']).to eq 'OrderedCollection'
|
||||
expect(json['orderedItems']).to eq [ActivityPub::TagManager.instance.uri_for(bookmark.status)]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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) }
|
||||
|
||||
@@ -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) }
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }
|
||||
|
||||
|
||||
@@ -5,27 +5,27 @@ 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 MAX_CHARS characters' do
|
||||
chars = StatusLengthValidator::MAX_CHARS + 1
|
||||
status = double(spoiler_text: 'a' * chars, text: '', errors: double(add: nil), local?: true, reblog?: false)
|
||||
status = instance_double(Status, spoiler_text: 'a' * chars, 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 MAX_CHARS characters' do
|
||||
chars = StatusLengthValidator::MAX_CHARS + 1
|
||||
status = double(spoiler_text: '', text: 'a' * chars, errors: double(add: nil), local?: true, reblog?: false)
|
||||
status = instance_double(Status, spoiler_text: '', text: 'a' * chars, errors: activemodel_errors, local?: true, reblog?: false)
|
||||
subject.validate(status)
|
||||
expect(status.errors).to have_received(:add)
|
||||
end
|
||||
@@ -33,7 +33,7 @@ describe StatusLengthValidator do
|
||||
it 'adds an error when text and content warning are over MAX_CHARS characters total' do
|
||||
chars1 = 20
|
||||
chars2 = StatusLengthValidator::MAX_CHARS + 1 - chars1
|
||||
status = double(spoiler_text: 'a' * chars1, text: 'b' * chars2, errors: double(add: nil), local?: true, reblog?: false)
|
||||
status = instance_double(Status, spoiler_text: 'a' * chars1, text: 'b' * chars2, errors: activemodel_errors, local?: true, reblog?: false)
|
||||
subject.validate(status)
|
||||
expect(status.errors).to have_received(:add)
|
||||
end
|
||||
@@ -41,7 +41,7 @@ describe StatusLengthValidator do
|
||||
it 'counts URLs as 23 characters flat' do
|
||||
chars = StatusLengthValidator::MAX_CHARS - 1 - 23
|
||||
text = ('a' * chars) + " 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)
|
||||
@@ -49,7 +49,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)
|
||||
@@ -57,7 +57,7 @@ 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
|
||||
@@ -66,7 +66,7 @@ describe StatusLengthValidator do
|
||||
username = '@alice'
|
||||
chars = StatusLengthValidator::MAX_CHARS - 1 - username.length
|
||||
text = ('a' * chars) + " #{username}@#{'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)
|
||||
@@ -74,10 +74,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
|
||||
|
||||
@@ -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' }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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 }
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 }
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -75,6 +75,12 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
around do |example|
|
||||
Timeout.timeout(30) do
|
||||
example.run
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
# Policies for the accounts
|
||||
Fabricate(:account_statuses_cleanup_policy, account: account_alice)
|
||||
|
||||
Reference in New Issue
Block a user