Merge remote-tracking branch 'parent/main' into upstream-20250328

This commit is contained in:
KMY 2025-03-28 08:44:30 +09:00
commit 12ed20b6d5
257 changed files with 3505 additions and 2010 deletions

View file

@ -1,130 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe ActivityPub::CollectionsController do
let!(:account) { Fabricate(:account) }
let!(:private_pinned) { Fabricate(:status, account: account, text: 'secret private stuff', visibility: :private) }
let(:remote_account) { nil }
before do
allow(controller).to receive(:signed_request_actor).and_return(remote_account)
Fabricate(:status_pin, account: account)
Fabricate(:status_pin, account: account)
Fabricate(:status_pin, account: account, status: private_pinned)
Fabricate(:status, account: account, visibility: :private)
end
describe 'GET #show' do
subject(:response) { get :show, params: { id: id, account_username: account.username } }
context 'when id is "featured"' do
let(:id) { 'featured' }
context 'without signature' do
let(:remote_account) { nil }
it 'returns http success and correct media type and correct items' do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers
expect(response.media_type).to eq 'application/activity+json'
expect(response.parsed_body[:orderedItems])
.to be_an(Array)
.and have_attributes(size: 3)
.and include(ActivityPub::TagManager.instance.uri_for(private_pinned))
.and not_include(private_pinned.text)
end
context 'when account is permanently suspended' do
before do
account.suspend!
account.deletion_request.destroy
end
it 'returns http gone' do
expect(response).to have_http_status(410)
end
end
context 'when account is temporarily suspended' do
before do
account.suspend!
end
it 'returns http forbidden' do
expect(response).to have_http_status(403)
end
end
end
context 'with signature' do
let(:remote_account) { Fabricate(:account, domain: 'example.com') }
context 'when getting a featured resource' do
it 'returns http success and correct media type and expected items' do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers
expect(response.media_type).to eq 'application/activity+json'
expect(response.parsed_body[:orderedItems])
.to be_an(Array)
.and have_attributes(size: 3)
.and include(ActivityPub::TagManager.instance.uri_for(private_pinned))
.and not_include(private_pinned.text)
end
end
context 'with authorized fetch mode' do
before do
allow(controller).to receive(:authorized_fetch_mode?).and_return(true)
end
context 'when signed request account is blocked' do
before do
account.block!(remote_account)
end
it 'returns http success and correct media type and cache headers and empty items' do
expect(response).to have_http_status(200)
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Cache-Control']).to include 'private'
expect(response.parsed_body[:orderedItems])
.to be_an(Array)
.and be_empty
end
end
context 'when signed request account is domain blocked' do
before do
account.block_domain!(remote_account.domain)
end
it 'returns http success and correct media type and cache headers and empty items' do
expect(response).to have_http_status(200)
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Cache-Control']).to include 'private'
expect(response.parsed_body[:orderedItems])
.to be_an(Array)
.and be_empty
end
end
end
end
end
context 'when id is not "featured"' do
let(:id) { 'hoge' }
it 'returns http not found' do
expect(response).to have_http_status(404)
end
end
end
end

View file

@ -1,75 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe ActivityPub::FollowersSynchronizationsController do
let!(:account) { Fabricate(:account) }
let!(:follower_example_com_user_a) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/users/a') }
let!(:follower_example_com_user_b) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/users/b') }
let!(:follower_foo_com_user_a) { Fabricate(:account, domain: 'foo.com', uri: 'https://foo.com/users/a') }
let!(:follower_example_com_instance_actor) { Fabricate(:account, username: 'instance-actor', domain: 'example.com', uri: 'https://example.com') }
before do
follower_example_com_user_a.follow!(account)
follower_example_com_user_b.follow!(account)
follower_foo_com_user_a.follow!(account)
follower_example_com_instance_actor.follow!(account)
allow(controller).to receive(:signed_request_actor).and_return(remote_account)
end
describe 'GET #show' do
context 'without signature' do
let(:remote_account) { nil }
before do
get :show, params: { account_username: account.username }
end
it 'returns http not authorized' do
expect(response).to have_http_status(401)
end
end
context 'with signature from example.com' do
subject(:response) { get :show, params: { account_username: account.username } }
let(:remote_account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/instance') }
it 'returns http success and cache control and activity json types and correct items' do
expect(response).to have_http_status(200)
expect(response.headers['Cache-Control']).to eq 'max-age=0, private'
expect(response.media_type).to eq 'application/activity+json'
expect(response.parsed_body[:orderedItems])
.to be_an(Array)
.and contain_exactly(
follower_example_com_instance_actor.uri,
follower_example_com_user_a.uri,
follower_example_com_user_b.uri
)
end
context 'when account is permanently suspended' do
before do
account.suspend!
account.deletion_request.destroy
end
it 'returns http gone' do
expect(response).to have_http_status(410)
end
end
context 'when account is temporarily suspended' do
before do
account.suspend!
end
it 'returns http forbidden' do
expect(response).to have_http_status(403)
end
end
end
end
end

View file

@ -1,112 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe ActivityPub::InboxesController do
let(:remote_account) { nil }
before do
allow(controller).to receive(:signed_request_actor).and_return(remote_account)
end
describe 'POST #create' do
context 'with signature' do
let(:remote_account) { Fabricate(:account, domain: 'example.com', protocol: :activitypub) }
before do
post :create, body: '{}'
end
it 'returns http accepted' do
expect(response).to have_http_status(202)
end
context 'with a specific account' do
subject(:response) { post :create, params: { account_username: account.username }, body: '{}' }
let(:account) { Fabricate(:account) }
context 'when account is permanently suspended' do
before do
account.suspend!
account.deletion_request.destroy
end
it 'returns http gone' do
expect(response).to have_http_status(410)
end
end
context 'when account is temporarily suspended' do
before do
account.suspend!
end
it 'returns http accepted' do
expect(response).to have_http_status(202)
end
end
end
end
context 'with Collection-Synchronization header' do
let(:remote_account) { Fabricate(:account, followers_url: 'https://example.com/followers', domain: 'example.com', uri: 'https://example.com/actor', protocol: :activitypub) }
let(:synchronization_collection) { remote_account.followers_url }
let(:synchronization_url) { 'https://example.com/followers-for-domain' }
let(:synchronization_hash) { 'somehash' }
let(:synchronization_header) { "collectionId=\"#{synchronization_collection}\", digest=\"#{synchronization_hash}\", url=\"#{synchronization_url}\"" }
before do
allow(ActivityPub::FollowersSynchronizationWorker).to receive(:perform_async).and_return(nil)
allow(remote_account).to receive(:local_followers_hash).and_return('somehash')
request.headers['Collection-Synchronization'] = synchronization_header
post :create, body: '{}'
end
context 'with mismatching target collection' do
let(:synchronization_collection) { 'https://example.com/followers2' }
it 'does not start a synchronization job' do
expect(ActivityPub::FollowersSynchronizationWorker).to_not have_received(:perform_async)
end
end
context 'with mismatching domain in partial collection attribute' do
let(:synchronization_url) { 'https://example.org/followers' }
it 'does not start a synchronization job' do
expect(ActivityPub::FollowersSynchronizationWorker).to_not have_received(:perform_async)
end
end
context 'with matching digest' do
it 'does not start a synchronization job' do
expect(ActivityPub::FollowersSynchronizationWorker).to_not have_received(:perform_async)
end
end
context 'with mismatching digest' do
let(:synchronization_hash) { 'wronghash' }
it 'starts a synchronization job' do
expect(ActivityPub::FollowersSynchronizationWorker).to have_received(:perform_async)
end
end
it 'returns http accepted' do
expect(response).to have_http_status(202)
end
end
context 'without signature' do
before do
post :create, body: '{}'
end
it 'returns http not authorized' do
expect(response).to have_http_status(401)
end
end
end
end

View file

@ -1,197 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe ActivityPub::OutboxesController do
let!(:account) { Fabricate(:account) }
before do
Fabricate(:status, account: account, visibility: :public)
Fabricate(:status, account: account, visibility: :unlisted)
Fabricate(:status, account: account, visibility: :private)
Fabricate(:status, account: account, visibility: :direct)
Fabricate(:status, account: account, visibility: :limited)
allow(controller).to receive(:signed_request_actor).and_return(remote_account)
end
describe 'GET #show' do
context 'without signature' do
subject(:response) { get :show, params: { account_username: account.username, page: page } }
let(:remote_account) { nil }
context 'with page not requested' do
let(:page) { nil }
it 'returns http success and correct media type and headers and items count' do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Vary']).to be_nil
expect(response.parsed_body[:totalItems]).to eq 4
end
context 'when account is permanently suspended' do
before do
account.suspend!
account.deletion_request.destroy
end
it 'returns http gone' do
expect(response).to have_http_status(410)
end
end
context 'when account is temporarily suspended' do
before do
account.suspend!
end
it 'returns http forbidden' do
expect(response).to have_http_status(403)
end
end
end
context 'with page requested' do
let(:page) { 'true' }
it 'returns http success and correct media type and vary header and items' do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Vary']).to include 'Signature'
expect(response.parsed_body)
.to include(
orderedItems: be_an(Array)
.and(have_attributes(size: 2))
.and(all(satisfy { |item| targets_public_collection?(item) }))
)
end
context 'when account is permanently suspended' do
before do
account.suspend!
account.deletion_request.destroy
end
it 'returns http gone' do
expect(response).to have_http_status(410)
end
end
context 'when account is temporarily suspended' do
before do
account.suspend!
end
it 'returns http forbidden' do
expect(response).to have_http_status(403)
end
end
end
end
context 'with signature' do
let(:remote_account) { Fabricate(:account, domain: 'example.com') }
let(:page) { 'true' }
context 'when signed request account does not follow account' do
before do
get :show, params: { account_username: account.username, page: page }
end
it 'returns http success and correct media type and headers and items' do
expect(response).to have_http_status(200)
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
expect(response.parsed_body)
.to include(
orderedItems: be_an(Array)
.and(have_attributes(size: 2))
.and(all(satisfy { |item| targets_public_collection?(item) }))
)
end
end
context 'when signed request account follows account' do
before do
remote_account.follow!(account)
get :show, params: { account_username: account.username, page: page }
end
it 'returns http success and correct media type and headers and items' do
expect(response).to have_http_status(200)
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
expect(response.parsed_body)
.to include(
orderedItems: be_an(Array)
.and(have_attributes(size: 3))
.and(all(satisfy { |item| targets_public_collection?(item) || targets_followers_collection?(item, account) }))
)
end
end
context 'when signed request account is blocked' do
before do
account.block!(remote_account)
get :show, params: { account_username: account.username, page: page }
end
it 'returns http success and correct media type and headers and items' do
expect(response).to have_http_status(200)
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
expect(response.parsed_body)
.to include(
orderedItems: be_an(Array).and(be_empty)
)
end
end
context 'when signed request account is domain blocked' do
before do
account.block_domain!(remote_account.domain)
get :show, params: { account_username: account.username, page: page }
end
it 'returns http success and correct media type and headers and items' do
expect(response).to have_http_status(200)
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
expect(response.parsed_body)
.to include(
orderedItems: be_an(Array).and(be_empty)
)
end
end
end
end
private
def ap_public_collection
ActivityPub::TagManager::COLLECTIONS[:public]
end
def targets_public_collection?(item)
item[:to].include?(ap_public_collection) || item[:cc].include?(ap_public_collection)
end
def targets_followers_collection?(item, account)
item[:to].include?(
account_followers_url(account, ActionMailer::Base.default_url_options)
)
end
end

View file

@ -1,250 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe ActivityPub::RepliesController do
let(:status) { Fabricate(:status, visibility: parent_visibility) }
let(:remote_account) { Fabricate(:account, domain: 'foobar.com') }
let(:remote_reply_id) { 'https://foobar.com/statuses/1234' }
let(:remote_querier) { nil }
shared_examples 'common behavior' do
context 'when status is private' do
let(:parent_visibility) { :private }
it 'returns http not found' do
expect(response).to have_http_status(404)
end
end
context 'when status is direct' do
let(:parent_visibility) { :direct }
it 'returns http not found' do
expect(response).to have_http_status(404)
end
end
end
shared_examples 'disallowed access' do
context 'when status is public' do
let(:parent_visibility) { :public }
it 'returns http not found' do
expect(response).to have_http_status(404)
end
end
it_behaves_like 'common behavior'
end
shared_examples 'allowed access' do
context 'when account is permanently suspended' do
let(:parent_visibility) { :public }
before do
status.account.suspend!
status.account.deletion_request.destroy
end
it 'returns http gone' do
expect(response).to have_http_status(410)
end
end
context 'when account is temporarily suspended' do
let(:parent_visibility) { :public }
before do
status.account.suspend!
end
it 'returns http forbidden' do
expect(response).to have_http_status(403)
end
end
context 'when status is public' do
let(:parent_visibility) { :public }
it 'returns http success and correct media type' do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers
expect(response.media_type).to eq 'application/activity+json'
end
context 'without only_other_accounts' do
it "returns items with thread author's replies" do
expect(response.parsed_body)
.to include(
first: be_a(Hash).and(
include(
items: be_an(Array)
.and(have_attributes(size: 1))
.and(all(satisfy { |item| targets_public_collection?(item) }))
)
)
)
end
context 'when there are few self-replies' do
it 'points next to replies from other people' do
expect(response.parsed_body)
.to include(
first: be_a(Hash).and(
include(
next: satisfy { |value| (parsed_uri_query_values(value) & %w(only_other_accounts=true page=true)).any? }
)
)
)
end
end
context 'when there are many self-replies' do
before do
10.times { Fabricate(:status, account: status.account, thread: status, visibility: :public) }
end
it 'points next to other self-replies' do
expect(response.parsed_body)
.to include(
first: be_a(Hash).and(
include(
next: satisfy { |value| (parsed_uri_query_values(value) & %w(only_other_accounts=false page=true)).any? }
)
)
)
end
end
end
context 'with only_other_accounts' do
let(:only_other_accounts) { 'true' }
it 'returns items with other public or unlisted replies' do
expect(response.parsed_body)
.to include(
first: be_a(Hash).and(
include(items: be_an(Array).and(have_attributes(size: 3)))
)
)
end
it 'only inlines items that are local and public or unlisted replies' do
expect(inlined_replies)
.to all(satisfy { |item| targets_public_collection?(item) })
.and all(satisfy { |item| ActivityPub::TagManager.instance.local_uri?(item[:id]) })
end
it 'uses ids for remote toots' do
expect(remote_replies)
.to all(satisfy { |item| item.is_a?(String) && !ActivityPub::TagManager.instance.local_uri?(item) })
end
context 'when there are few replies' do
it 'does not have a next page' do
expect(response.parsed_body)
.to include(
first: be_a(Hash).and(not_include(next: be_present))
)
end
end
context 'when there are many replies' do
before do
10.times { Fabricate(:status, thread: status, visibility: :public) }
end
it 'points next to other replies' do
expect(response.parsed_body)
.to include(
first: be_a(Hash).and(
include(
next: satisfy { |value| (parsed_uri_query_values(value) & %w(only_other_accounts=true page=true)).any? }
)
)
)
end
end
end
end
it_behaves_like 'common behavior'
end
before do
stub_const 'ActivityPub::RepliesController::DESCENDANTS_LIMIT', 5
allow(controller).to receive(:signed_request_actor).and_return(remote_querier)
Fabricate(:status, thread: status, visibility: :public)
Fabricate(:status, thread: status, visibility: :public)
Fabricate(:status, thread: status, visibility: :private)
Fabricate(:status, account: status.account, thread: status, visibility: :public)
Fabricate(:status, account: status.account, thread: status, visibility: :private)
Fabricate(:status, account: remote_account, thread: status, visibility: :public, uri: remote_reply_id)
end
describe 'GET #index' do
subject(:response) { get :index, params: { account_username: status.account.username, status_id: status.id, only_other_accounts: only_other_accounts } }
let(:only_other_accounts) { nil }
context 'with no signature' do
it_behaves_like 'allowed access'
end
context 'with signature' do
let(:remote_querier) { Fabricate(:account, domain: 'example.com') }
it_behaves_like 'allowed access'
context 'when signed request account is blocked' do
before do
status.account.block!(remote_querier)
end
it_behaves_like 'disallowed access'
end
context 'when signed request account is domain blocked' do
before do
status.account.block_domain!(remote_querier.domain)
end
it_behaves_like 'disallowed access'
end
end
end
private
def inlined_replies
response
.parsed_body[:first][:items]
.select { |x| x.is_a?(Hash) }
end
def remote_replies
response
.parsed_body[:first][:items]
.reject { |x| x.is_a?(Hash) }
end
def parsed_uri_query_values(uri)
Addressable::URI
.parse(uri)
.query
.split('&')
end
def ap_public_collection
ActivityPub::TagManager::COLLECTIONS[:public]
end
def targets_public_collection?(item)
item[:to].include?(ap_public_collection) || item[:cc].include?(ap_public_collection)
end
end

View file

@ -1,35 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Admin::AccountActionsController do
render_views
let(:user) { Fabricate(:admin_user) }
before do
sign_in user, scope: :user
end
describe 'GET #new' do
let(:account) { Fabricate(:account) }
it 'returns http success' do
get :new, params: { account_id: account.id }
expect(response).to have_http_status(:success)
end
end
describe 'POST #create' do
let(:account) { Fabricate(:account) }
it 'records the account action' do
expect do
post :create, params: { account_id: account.id, admin_account_action: { type: 'silence' } }
end.to change { account.strikes.count }.by(1)
expect(response).to redirect_to(admin_account_path(account.id))
end
end
end

View file

@ -1,48 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Admin::ActionLogsController do
render_views
# Action logs typically cause issues when their targets are not in the database
let!(:account) { Fabricate(:account) }
before do
orphaned_log_types.map do |type|
Fabricate(:action_log, account: account, action: 'destroy', target_type: type, target_id: 1312)
end
end
describe 'GET #index' do
it 'returns 200' do
sign_in Fabricate(:admin_user)
get :index, params: { page: 1 }
expect(response).to have_http_status(200)
end
end
private
def orphaned_log_types
%w(
Account
AccountWarning
Announcement
Appeal
CanonicalEmailBlock
CustomEmoji
DomainAllow
DomainBlock
EmailDomainBlock
Instance
IpBlock
Report
Status
UnavailableDomain
User
UserRole
)
end
end

View file

@ -1,48 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Admin::ChangeEmailsController do
render_views
let(:admin) { Fabricate(:admin_user) }
before do
sign_in admin
end
describe 'GET #show' do
it 'returns http success' do
user = Fabricate(:user)
get :show, params: { account_id: user.account.id }
expect(response).to have_http_status(200)
end
end
describe 'GET #update' do
before do
allow(UserMailer).to receive(:confirmation_instructions)
.and_return(instance_double(ActionMailer::MessageDelivery, deliver_later: nil))
end
it 'returns http success' do
user = Fabricate(:user)
previous_email = user.email
post :update, params: { account_id: user.account.id, user: { unconfirmed_email: 'test@example.com' } }
user.reload
expect(user.email).to eq previous_email
expect(user.unconfirmed_email).to eq 'test@example.com'
expect(user.confirmation_token).to_not be_nil
expect(UserMailer).to have_received(:confirmation_instructions).with(user, user.confirmation_token, { to: 'test@example.com' })
expect(response).to redirect_to(admin_account_path(user.account.id))
end
end
end

View file

@ -1,35 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Admin::DashboardController do
render_views
describe 'GET #index' do
let(:user) { Fabricate(:owner_user) }
before do
stub_system_checks
Fabricate :software_update
sign_in(user)
end
it 'returns http success and body with system check messages' do
get :index
expect(response)
.to have_http_status(200)
.and have_attributes(
body: include(I18n.t('admin.system_checks.software_version_patch_check.message_html'))
)
end
private
def stub_system_checks
stub_const 'Admin::SystemCheck::ACTIVE_CHECKS', [
Admin::SystemCheck::SoftwareVersionCheck,
]
end
end
end

View file

@ -1,54 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
require 'webauthn/fake_client'
RSpec.describe Admin::Users::TwoFactorAuthenticationsController do
render_views
let(:user) { Fabricate(:user) }
before do
sign_in Fabricate(:admin_user), scope: :user
end
describe 'DELETE #destroy' do
context 'when user has OTP enabled' do
before do
user.update(otp_required_for_login: true)
end
it 'redirects to admin account page' do
delete :destroy, params: { user_id: user.id }
user.reload
expect(user.otp_enabled?).to be false
expect(response).to redirect_to(admin_account_path(user.account_id))
end
end
context 'when user has OTP and WebAuthn enabled' do
let(:fake_client) { WebAuthn::FakeClient.new('http://test.host') }
before do
user.update(otp_required_for_login: true, webauthn_id: WebAuthn.generate_user_id)
public_key_credential = WebAuthn::Credential.from_create(fake_client.create)
Fabricate(:webauthn_credential,
user_id: user.id,
external_id: public_key_credential.id,
public_key: public_key_credential.public_key,
nickname: 'Security Key')
end
it 'redirects to admin account page' do
delete :destroy, params: { user_id: user.id }
user.reload
expect(user.otp_enabled?).to be false
expect(user.webauthn_enabled?).to be false
expect(response).to redirect_to(admin_account_path(user.account_id))
end
end
end
end

View file

@ -342,6 +342,42 @@ RSpec.describe Auth::RegistrationsController do
end
end
context 'when age verification is enabled' do
subject { post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' }.merge(date_of_birth) } }
before do
Setting.min_age = 16
end
let(:date_of_birth) { {} }
context 'when date of birth is below age limit' do
let(:date_of_birth) { 13.years.ago.then { |date| { 'date_of_birth(1i)': date.day.to_s, 'date_of_birth(2i)': date.month.to_s, 'date_of_birth(3i)': date.year.to_s } } }
it 'does not create user' do
subject
user = User.find_by(email: 'test@example.com')
expect(user).to be_nil
end
end
context 'when date of birth is above age limit' do
let(:date_of_birth) { 17.years.ago.then { |date| { 'date_of_birth(1i)': date.day.to_s, 'date_of_birth(2i)': date.month.to_s, 'date_of_birth(3i)': date.year.to_s } } }
it 'redirects to setup and creates user' do
subject
expect(response).to redirect_to auth_setup_path
expect(User.find_by(email: 'test@example.com'))
.to be_present
.and have_attributes(
age_verified_at: not_eq(nil)
)
end
end
end
context 'when max user count is set' do
subject do
post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' } }

View file

@ -1,32 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Disputes::StrikesController do
render_views
before { sign_in current_user, scope: :user }
describe '#show' do
let(:current_user) { Fabricate(:user) }
let(:strike) { Fabricate(:account_warning, target_account: current_user.account) }
before do
get :show, params: { id: strike.id }
end
context 'when meant for the user' do
it 'returns http success' do
expect(response).to have_http_status(:success)
end
end
context 'when meant for a different user' do
let(:strike) { Fabricate(:account_warning) }
it 'returns http forbidden' do
expect(response).to have_http_status(403)
end
end
end
end

View file

@ -1,45 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Filters::StatusesController do
render_views
describe 'GET #index' do
let(:filter) { Fabricate(:custom_filter) }
context 'with signed out user' do
it 'redirects' do
get :index, params: { filter_id: filter }
expect(response).to be_redirect
end
end
context 'with a signed in user' do
context 'with the filter user signed in' do
before do
sign_in(filter.account.user)
get :index, params: { filter_id: filter }
end
it 'returns http success and private cache control headers' do
expect(response).to have_http_status(200)
expect(response.headers['Cache-Control']).to include('private, no-store')
end
end
context 'with another user signed in' do
before do
sign_in(Fabricate(:user))
get :index, params: { filter_id: filter }
end
it 'returns http not found' do
expect(response).to have_http_status(404)
end
end
end
end
end

View file

@ -1,53 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe IntentsController do
render_views
let(:user) { Fabricate(:user) }
before { sign_in user, scope: :user }
describe 'GET #show' do
subject { get :show, params: { uri: uri } }
context 'when schema is web+mastodon' do
context 'when host is follow' do
let(:uri) { 'web+mastodon://follow?uri=test' }
it { is_expected.to redirect_to authorize_interaction_path(uri: 'test') }
end
context 'when host is share' do
let(:uri) { 'web+mastodon://share?text=test' }
it { is_expected.to redirect_to share_path(text: 'test') }
end
context 'when host is none of the above' do
let(:uri) { 'web+mastodon://test' }
it { is_expected.to have_http_status 404 }
end
end
context 'when schema is not web+mastodon' do
let(:uri) { 'api+mastodon://test.com' }
it { is_expected.to have_http_status 404 }
end
context 'when uri param is blank' do
let(:uri) { '' }
it { is_expected.to have_http_status 404 }
end
context 'when uri is invalid' do
let(:uri) { 'invalid uri://test.com' }
it { is_expected.to have_http_status 404 }
end
end
end

View file

@ -1,23 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Oauth::TokensController do
describe 'POST #revoke' do
let!(:user) { Fabricate(:user) }
let!(:application) { Fabricate(:application, confidential: false) }
let!(:access_token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: application) }
let!(:web_push_subscription) { Fabricate(:web_push_subscription, user: user, access_token: access_token) }
it 'revokes the token and removes subscriptions' do
post :revoke, params: { client_id: application.uid, token: access_token.token }
expect(access_token.reload.revoked_at)
.to_not be_nil
expect(Web::PushSubscription.where(access_token: access_token).count)
.to eq(0)
expect { web_push_subscription.reload }
.to raise_error(ActiveRecord::RecordNotFound)
end
end
end

View file

@ -1,87 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Settings::DeletesController do
render_views
describe 'GET #show' do
context 'when signed in' do
let(:user) { Fabricate(:user) }
before do
sign_in user, scope: :user
get :show
end
it 'renders confirmation page with private cache control headers', :aggregate_failures do
expect(response).to have_http_status(200)
expect(response.headers['Cache-Control']).to include('private, no-store')
end
context 'when suspended' do
let(:user) { Fabricate(:user, account_attributes: { suspended_at: Time.now.utc }) }
it 'returns http forbidden with private cache control headers', :aggregate_failures do
expect(response).to have_http_status(403)
expect(response.headers['Cache-Control']).to include('private, no-store')
end
end
end
context 'when not signed in' do
it 'redirects' do
get :show
expect(response).to redirect_to '/auth/sign_in'
end
end
end
describe 'DELETE #destroy' do
context 'when signed in' do
let(:user) { Fabricate(:user, password: 'petsmoldoggos') }
before do
sign_in user, scope: :user
end
context 'with correct password' do
before do
delete :destroy, params: { form_delete_confirmation: { password: 'petsmoldoggos' } }
end
it 'removes user record and redirects', :aggregate_failures, :inline_jobs do
expect(response).to redirect_to '/auth/sign_in'
expect(User.find_by(id: user.id)).to be_nil
expect(user.account.reload).to be_suspended
expect(CanonicalEmailBlock.block?(user.email)).to be false
end
context 'when suspended' do
let(:user) { Fabricate(:user, account_attributes: { suspended_at: Time.now.utc }) }
it 'returns http forbidden' do
expect(response).to have_http_status(403)
end
end
end
context 'with incorrect password' do
before do
delete :destroy, params: { form_delete_confirmation: { password: 'blaze420' } }
end
it 'redirects back to confirmation page' do
expect(response).to redirect_to settings_delete_path
end
end
end
context 'when not signed in' do
it 'redirects' do
delete :destroy
expect(response).to redirect_to '/auth/sign_in'
end
end
end
end