Merge remote-tracking branch 'parent/main' into upstream-20231109
This commit is contained in:
commit
fc1b280d59
65 changed files with 18502 additions and 13905 deletions
|
@ -26,7 +26,6 @@ describe Api::V1::StreamingController do
|
|||
context 'with streaming api on different host' do
|
||||
before do
|
||||
Rails.configuration.x.streaming_api_base_url = "wss://streaming-#{Rails.configuration.x.web_domain}"
|
||||
@streaming_host = URI.parse(Rails.configuration.x.streaming_api_base_url).host
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
|
@ -38,7 +37,13 @@ describe Api::V1::StreamingController do
|
|||
[:scheme, :path, :query, :fragment].each do |part|
|
||||
expect(redirect_to_uri.send(part)).to eq(request_uri.send(part)), "redirect target #{part}"
|
||||
end
|
||||
expect(redirect_to_uri.host).to eq(@streaming_host), 'redirect target host'
|
||||
expect(redirect_to_uri.host).to eq(streaming_host), 'redirect target host'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def streaming_host
|
||||
URI.parse(Rails.configuration.x.streaming_api_base_url).host
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@ describe Auth::ConfirmationsController do
|
|||
|
||||
describe 'GET #new' do
|
||||
it 'returns http success' do
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
get :new
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
@ -19,7 +19,7 @@ describe Auth::ConfirmationsController do
|
|||
|
||||
before do
|
||||
allow(BootstrapTimelineWorker).to receive(:perform_async)
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
get :show, params: { confirmation_token: 'foobar' }
|
||||
end
|
||||
|
||||
|
@ -37,7 +37,7 @@ describe Auth::ConfirmationsController do
|
|||
|
||||
before do
|
||||
allow(BootstrapTimelineWorker).to receive(:perform_async)
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
get :show, params: { confirmation_token: 'foobar' }
|
||||
end
|
||||
|
||||
|
@ -51,7 +51,7 @@ describe Auth::ConfirmationsController do
|
|||
|
||||
before do
|
||||
allow(BootstrapTimelineWorker).to receive(:perform_async)
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
sign_in(user, scope: :user)
|
||||
get :show, params: { confirmation_token: 'foobar' }
|
||||
end
|
||||
|
@ -66,7 +66,7 @@ describe Auth::ConfirmationsController do
|
|||
|
||||
before do
|
||||
allow(BootstrapTimelineWorker).to receive(:perform_async)
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
user.approved = false
|
||||
user.save!
|
||||
sign_in(user, scope: :user)
|
||||
|
@ -83,7 +83,7 @@ describe Auth::ConfirmationsController do
|
|||
|
||||
before do
|
||||
allow(BootstrapTimelineWorker).to receive(:perform_async)
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
get :show, params: { confirmation_token: 'foobar' }
|
||||
end
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ describe Auth::PasswordsController do
|
|||
|
||||
describe 'GET #new' do
|
||||
it 'returns http success' do
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
get :new
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
@ -18,12 +18,14 @@ describe Auth::PasswordsController do
|
|||
|
||||
before do
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
@token = user.send_reset_password_instructions
|
||||
end
|
||||
|
||||
context 'with valid reset_password_token' do
|
||||
it 'returns http success' do
|
||||
get :edit, params: { reset_password_token: @token }
|
||||
token = user.send_reset_password_instructions
|
||||
|
||||
get :edit, params: { reset_password_token: token }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
@ -38,9 +40,9 @@ describe Auth::PasswordsController do
|
|||
|
||||
describe 'POST #update' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:password) { 'reset0password' }
|
||||
|
||||
before do
|
||||
@password = 'reset0password'
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
end
|
||||
|
||||
|
@ -50,9 +52,9 @@ describe Auth::PasswordsController do
|
|||
let!(:web_push_subscription) { Fabricate(:web_push_subscription, access_token: access_token) }
|
||||
|
||||
before do
|
||||
@token = user.send_reset_password_instructions
|
||||
token = user.send_reset_password_instructions
|
||||
|
||||
post :update, params: { user: { password: @password, password_confirmation: @password, reset_password_token: @token } }
|
||||
post :update, params: { user: { password: password, password_confirmation: password, reset_password_token: token } }
|
||||
end
|
||||
|
||||
it 'redirect to sign in' do
|
||||
|
@ -63,7 +65,7 @@ describe Auth::PasswordsController do
|
|||
this_user = User.find(user.id)
|
||||
|
||||
expect(this_user).to_not be_nil
|
||||
expect(this_user.valid_password?(@password)).to be true
|
||||
expect(this_user.valid_password?(password)).to be true
|
||||
end
|
||||
|
||||
it 'deactivates all sessions' do
|
||||
|
@ -81,7 +83,7 @@ describe Auth::PasswordsController do
|
|||
|
||||
context 'with invalid reset_password_token' do
|
||||
before do
|
||||
post :update, params: { user: { password: @password, password_confirmation: @password, reset_password_token: 'some_invalid_value' } }
|
||||
post :update, params: { user: { password: password, password_confirmation: password, reset_password_token: 'some_invalid_value' } }
|
||||
end
|
||||
|
||||
it 'renders reset password' do
|
||||
|
|
|
@ -378,7 +378,7 @@ RSpec.describe Auth::SessionsController do
|
|||
|
||||
context 'when using a valid webauthn credential' do
|
||||
before do
|
||||
@controller.session[:webauthn_challenge] = challenge
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
|
||||
post :create, params: { user: { credential: fake_credential } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
|
||||
end
|
||||
|
|
|
@ -11,7 +11,7 @@ describe ExportControllerConcern do
|
|||
end
|
||||
|
||||
def export_data
|
||||
@export.account.username
|
||||
'body data value'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -24,7 +24,7 @@ describe ExportControllerConcern do
|
|||
expect(response).to have_http_status(200)
|
||||
expect(response.media_type).to eq 'text/csv'
|
||||
expect(response.headers['Content-Disposition']).to start_with 'attachment; filename="anonymous.csv"'
|
||||
expect(response.body).to eq user.account.username
|
||||
expect(response.body).to eq 'body data value'
|
||||
end
|
||||
|
||||
it 'returns unauthorized when not signed in' do
|
||||
|
|
|
@ -10,7 +10,7 @@ RSpec.describe HomeController do
|
|||
|
||||
context 'when not signed in' do
|
||||
it 'returns http success' do
|
||||
@request.path = '/'
|
||||
request.path = '/'
|
||||
expect(subject).to have_http_status(:success)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -194,7 +194,7 @@ RSpec.describe Settings::ImportsController do
|
|||
let!(:rows) do
|
||||
[
|
||||
{ 'acct' => 'foo@bar' },
|
||||
{ 'acct' => 'user@bar', 'show_reblogs' => false, 'notify' => true, 'languages' => ['fr', 'de'] },
|
||||
{ 'acct' => 'user@bar', 'show_reblogs' => false, 'notify' => true, 'languages' => %w(fr de) },
|
||||
].map { |data| Fabricate(:bulk_import_row, bulk_import: bulk_import, data: data) }
|
||||
end
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
|
|||
it 'stores the challenge on the session' do
|
||||
get :options
|
||||
|
||||
expect(@controller.session[:webauthn_challenge]).to be_present
|
||||
expect(controller.session[:webauthn_challenge]).to be_present
|
||||
end
|
||||
|
||||
it 'does not change webauthn_id' do
|
||||
|
@ -155,7 +155,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
|
|||
it 'stores the challenge on the session' do
|
||||
get :options
|
||||
|
||||
expect(@controller.session[:webauthn_challenge]).to be_present
|
||||
expect(controller.session[:webauthn_challenge]).to be_present
|
||||
end
|
||||
|
||||
it 'sets user webauthn_id' do
|
||||
|
@ -218,7 +218,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
|
|||
|
||||
context 'when creation succeeds' do
|
||||
it 'returns http success' do
|
||||
@controller.session[:webauthn_challenge] = challenge
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
|
||||
post :create, params: { credential: new_webauthn_credential, nickname: nickname }
|
||||
|
||||
|
@ -226,7 +226,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
|
|||
end
|
||||
|
||||
it 'adds a new credential to user credentials' do
|
||||
@controller.session[:webauthn_challenge] = challenge
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
|
||||
expect do
|
||||
post :create, params: { credential: new_webauthn_credential, nickname: nickname }
|
||||
|
@ -234,7 +234,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
|
|||
end
|
||||
|
||||
it 'does not change webauthn_id' do
|
||||
@controller.session[:webauthn_challenge] = challenge
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
|
||||
expect do
|
||||
post :create, params: { credential: new_webauthn_credential, nickname: nickname }
|
||||
|
@ -244,7 +244,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
|
|||
|
||||
context 'when the nickname is already used' do
|
||||
it 'fails' do
|
||||
@controller.session[:webauthn_challenge] = challenge
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
|
||||
post :create, params: { credential: new_webauthn_credential, nickname: 'USB Key' }
|
||||
|
||||
|
@ -264,7 +264,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
|
|||
end
|
||||
|
||||
it 'fails' do
|
||||
@controller.session[:webauthn_challenge] = challenge
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
|
||||
post :create, params: { credential: new_webauthn_credential, nickname: nickname }
|
||||
|
||||
|
@ -277,7 +277,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
|
|||
context 'when user have not enabled webauthn' do
|
||||
context 'when creation succeeds' do
|
||||
it 'creates a webauthn credential' do
|
||||
@controller.session[:webauthn_challenge] = challenge
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
|
||||
expect do
|
||||
post :create, params: { credential: new_webauthn_credential, nickname: nickname }
|
||||
|
|
|
@ -5,9 +5,10 @@ require 'rails_helper'
|
|||
RSpec.describe StatusesCleanupController do
|
||||
render_views
|
||||
|
||||
let!(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
@user = Fabricate(:user)
|
||||
sign_in @user, scope: :user
|
||||
sign_in user, scope: :user
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
|
@ -30,9 +31,9 @@ RSpec.describe StatusesCleanupController do
|
|||
end
|
||||
|
||||
it 'updates the account status cleanup policy' do
|
||||
expect(@user.account.statuses_cleanup_policy.enabled).to be true
|
||||
expect(@user.account.statuses_cleanup_policy.keep_direct).to be false
|
||||
expect(@user.account.statuses_cleanup_policy.keep_polls).to be true
|
||||
expect(user.account.statuses_cleanup_policy.enabled).to be true
|
||||
expect(user.account.statuses_cleanup_policy.keep_direct).to be false
|
||||
expect(user.account.statuses_cleanup_policy.keep_polls).to be true
|
||||
end
|
||||
|
||||
it 'redirects' do
|
||||
|
|
|
@ -8,12 +8,14 @@ RSpec.describe TranslationService::DeepL do
|
|||
let(:plan) { 'advanced' }
|
||||
|
||||
before do
|
||||
stub_request(:get, 'https://api.deepl.com/v2/languages?type=source').to_return(
|
||||
body: '[{"language":"EN","name":"English"},{"language":"UK","name":"Ukrainian"}]'
|
||||
)
|
||||
stub_request(:get, 'https://api.deepl.com/v2/languages?type=target').to_return(
|
||||
body: '[{"language":"EN-GB","name":"English (British)"},{"language":"ZH","name":"Chinese"}]'
|
||||
)
|
||||
%w(api-free.deepl.com api.deepl.com).each do |host|
|
||||
stub_request(:get, "https://#{host}/v2/languages?type=source").to_return(
|
||||
body: '[{"language":"EN","name":"English"},{"language":"UK","name":"Ukrainian"}]'
|
||||
)
|
||||
stub_request(:get, "https://#{host}/v2/languages?type=target").to_return(
|
||||
body: '[{"language":"EN-GB","name":"English (British)"},{"language":"ZH","name":"Chinese"}]'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#translate' do
|
||||
|
@ -73,28 +75,25 @@ RSpec.describe TranslationService::DeepL do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#request' do
|
||||
describe 'the paid and free plan api hostnames' do
|
||||
before do
|
||||
stub_request(:any, //)
|
||||
# rubocop:disable Lint/EmptyBlock
|
||||
service.send(:request, :get, '/v2/languages') { |res| }
|
||||
# rubocop:enable Lint/EmptyBlock
|
||||
service.languages
|
||||
end
|
||||
|
||||
it 'uses paid plan base URL' do
|
||||
expect(a_request(:get, 'https://api.deepl.com/v2/languages')).to have_been_made.once
|
||||
end
|
||||
|
||||
context 'with free plan' do
|
||||
let(:plan) { 'free' }
|
||||
|
||||
it 'uses free plan base URL' do
|
||||
expect(a_request(:get, 'https://api-free.deepl.com/v2/languages')).to have_been_made.once
|
||||
context 'without a plan set' do
|
||||
it 'uses paid plan base URL and sends an API key' do
|
||||
expect(a_request(:get, 'https://api.deepl.com/v2/languages?type=source').with(headers: { Authorization: 'DeepL-Auth-Key my-api-key' })).to have_been_made.once
|
||||
expect(a_request(:get, 'https://api.deepl.com/v2/languages?type=target').with(headers: { Authorization: 'DeepL-Auth-Key my-api-key' })).to have_been_made.once
|
||||
end
|
||||
end
|
||||
|
||||
it 'sends API key' do
|
||||
expect(a_request(:get, 'https://api.deepl.com/v2/languages').with(headers: { Authorization: 'DeepL-Auth-Key my-api-key' })).to have_been_made.once
|
||||
context 'with the free plan' do
|
||||
let(:plan) { 'free' }
|
||||
|
||||
it 'uses free plan base URL and sends an API key' do
|
||||
expect(a_request(:get, 'https://api-free.deepl.com/v2/languages?type=source').with(headers: { Authorization: 'DeepL-Auth-Key my-api-key' })).to have_been_made.once
|
||||
expect(a_request(:get, 'https://api-free.deepl.com/v2/languages?type=target').with(headers: { Authorization: 'DeepL-Auth-Key my-api-key' })).to have_been_made.once
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,17 +4,15 @@ require 'rails_helper'
|
|||
|
||||
describe AccountFinderConcern do
|
||||
describe 'local finders' do
|
||||
before do
|
||||
@account = Fabricate(:account, username: 'Alice')
|
||||
end
|
||||
let!(:account) { Fabricate(:account, username: 'Alice') }
|
||||
|
||||
describe '.find_local' do
|
||||
it 'returns case-insensitive result' do
|
||||
expect(Account.find_local('alice')).to eq(@account)
|
||||
expect(Account.find_local('alice')).to eq(account)
|
||||
end
|
||||
|
||||
it 'returns correctly cased result' do
|
||||
expect(Account.find_local('Alice')).to eq(@account)
|
||||
expect(Account.find_local('Alice')).to eq(account)
|
||||
end
|
||||
|
||||
it 'returns nil without a match' do
|
||||
|
@ -36,7 +34,7 @@ describe AccountFinderConcern do
|
|||
|
||||
describe '.find_local!' do
|
||||
it 'returns matching result' do
|
||||
expect(Account.find_local!('alice')).to eq(@account)
|
||||
expect(Account.find_local!('alice')).to eq(account)
|
||||
end
|
||||
|
||||
it 'raises on non-matching result' do
|
||||
|
@ -54,17 +52,15 @@ describe AccountFinderConcern do
|
|||
end
|
||||
|
||||
describe 'remote finders' do
|
||||
before do
|
||||
@account = Fabricate(:account, username: 'Alice', domain: 'mastodon.social')
|
||||
end
|
||||
let!(:account) { Fabricate(:account, username: 'Alice', domain: 'mastodon.social') }
|
||||
|
||||
describe '.find_remote' do
|
||||
it 'returns exact match result' do
|
||||
expect(Account.find_remote('alice', 'mastodon.social')).to eq(@account)
|
||||
expect(Account.find_remote('alice', 'mastodon.social')).to eq(account)
|
||||
end
|
||||
|
||||
it 'returns case-insensitive result' do
|
||||
expect(Account.find_remote('ALICE', 'MASTODON.SOCIAL')).to eq(@account)
|
||||
expect(Account.find_remote('ALICE', 'MASTODON.SOCIAL')).to eq(account)
|
||||
end
|
||||
|
||||
it 'returns nil when username does not match' do
|
||||
|
@ -90,7 +86,7 @@ describe AccountFinderConcern do
|
|||
|
||||
describe '.find_remote!' do
|
||||
it 'returns matching result' do
|
||||
expect(Account.find_remote!('alice', 'mastodon.social')).to eq(@account)
|
||||
expect(Account.find_remote!('alice', 'mastodon.social')).to eq(account)
|
||||
end
|
||||
|
||||
it 'raises on non-matching result' do
|
||||
|
|
|
@ -650,38 +650,36 @@ describe AccountInteractions do
|
|||
end
|
||||
|
||||
describe 'ignoring reblogs from an account' do
|
||||
before do
|
||||
@me = Fabricate(:account, username: 'Me')
|
||||
@you = Fabricate(:account, username: 'You')
|
||||
end
|
||||
let!(:me) { Fabricate(:account, username: 'Me') }
|
||||
let!(:you) { Fabricate(:account, username: 'You') }
|
||||
|
||||
context 'with the reblogs option unspecified' do
|
||||
before do
|
||||
@me.follow!(@you)
|
||||
me.follow!(you)
|
||||
end
|
||||
|
||||
it 'defaults to showing reblogs' do
|
||||
expect(@me.muting_reblogs?(@you)).to be(false)
|
||||
expect(me.muting_reblogs?(you)).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with the reblogs option set to false' do
|
||||
before do
|
||||
@me.follow!(@you, reblogs: false)
|
||||
me.follow!(you, reblogs: false)
|
||||
end
|
||||
|
||||
it 'does mute reblogs' do
|
||||
expect(@me.muting_reblogs?(@you)).to be(true)
|
||||
expect(me.muting_reblogs?(you)).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with the reblogs option set to true' do
|
||||
before do
|
||||
@me.follow!(@you, reblogs: true)
|
||||
me.follow!(you, reblogs: true)
|
||||
end
|
||||
|
||||
it 'does not mute reblogs' do
|
||||
expect(@me.muting_reblogs?(@you)).to be(false)
|
||||
expect(me.muting_reblogs?(you)).to be(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -296,7 +296,7 @@ RSpec.describe Form::Import do
|
|||
|
||||
it_behaves_like 'on successful import', 'following', 'merge', 'following_accounts.csv', [
|
||||
{ 'acct' => 'user@example.com', 'show_reblogs' => true, 'notify' => false, 'languages' => nil },
|
||||
{ 'acct' => 'user@test.com', 'show_reblogs' => true, 'notify' => true, 'languages' => ['en', 'fr'] },
|
||||
{ 'acct' => 'user@test.com', 'show_reblogs' => true, 'notify' => true, 'languages' => %w(en fr) },
|
||||
]
|
||||
|
||||
it_behaves_like 'on successful import', 'muting', 'merge', 'muted_accounts.csv', [
|
||||
|
|
|
@ -209,15 +209,13 @@ RSpec.describe PublicFeed do
|
|||
end
|
||||
|
||||
describe 'with an account passed in' do
|
||||
subject { described_class.new(@account).get(20).map(&:id) }
|
||||
subject { described_class.new(account).get(20).map(&:id) }
|
||||
|
||||
before do
|
||||
@account = Fabricate(:account)
|
||||
end
|
||||
let!(:account) { Fabricate(:account) }
|
||||
|
||||
it 'excludes statuses from accounts blocked by the account' do
|
||||
blocked = Fabricate(:account)
|
||||
@account.block!(blocked)
|
||||
account.block!(blocked)
|
||||
blocked_status = Fabricate(:status, account: blocked)
|
||||
|
||||
expect(subject).to_not include(blocked_status.id)
|
||||
|
@ -225,7 +223,7 @@ RSpec.describe PublicFeed do
|
|||
|
||||
it 'excludes statuses from accounts who have blocked the account' do
|
||||
blocker = Fabricate(:account)
|
||||
blocker.block!(@account)
|
||||
blocker.block!(account)
|
||||
blocked_status = Fabricate(:status, account: blocker)
|
||||
|
||||
expect(subject).to_not include(blocked_status.id)
|
||||
|
@ -233,7 +231,7 @@ RSpec.describe PublicFeed do
|
|||
|
||||
it 'excludes statuses from accounts muted by the account' do
|
||||
muted = Fabricate(:account)
|
||||
@account.mute!(muted)
|
||||
account.mute!(muted)
|
||||
muted_status = Fabricate(:status, account: muted)
|
||||
|
||||
expect(subject).to_not include(muted_status.id)
|
||||
|
@ -241,7 +239,7 @@ RSpec.describe PublicFeed do
|
|||
|
||||
it 'excludes statuses from accounts from personally blocked domains' do
|
||||
blocked = Fabricate(:account, domain: 'example.com')
|
||||
@account.block_domain!(blocked.domain)
|
||||
account.block_domain!(blocked.domain)
|
||||
blocked_status = Fabricate(:status, account: blocked)
|
||||
|
||||
expect(subject).to_not include(blocked_status.id)
|
||||
|
@ -249,7 +247,7 @@ RSpec.describe PublicFeed do
|
|||
|
||||
context 'with language preferences' do
|
||||
it 'excludes statuses in languages not allowed by the account user' do
|
||||
@account.user.update(chosen_languages: [:en, :es])
|
||||
account.user.update(chosen_languages: [:en, :es])
|
||||
en_status = Fabricate(:status, language: 'en')
|
||||
es_status = Fabricate(:status, language: 'es')
|
||||
fr_status = Fabricate(:status, language: 'fr')
|
||||
|
@ -260,7 +258,7 @@ RSpec.describe PublicFeed do
|
|||
end
|
||||
|
||||
it 'includes all languages when user does not have a setting' do
|
||||
@account.user.update(chosen_languages: nil)
|
||||
account.user.update(chosen_languages: nil)
|
||||
|
||||
en_status = Fabricate(:status, language: 'en')
|
||||
es_status = Fabricate(:status, language: 'es')
|
||||
|
@ -270,7 +268,7 @@ RSpec.describe PublicFeed do
|
|||
end
|
||||
|
||||
it 'includes all languages when account does not have a user' do
|
||||
@account.update(user: nil)
|
||||
account.update(user: nil)
|
||||
|
||||
en_status = Fabricate(:status, language: 'en')
|
||||
es_status = Fabricate(:status, language: 'es')
|
||||
|
|
|
@ -11,10 +11,6 @@ if RUN_SYSTEM_SPECS
|
|||
ENV['STREAMING_API_BASE_URL'] = "http://localhost:#{STREAMING_PORT}"
|
||||
end
|
||||
|
||||
if RUN_SEARCH_SPECS
|
||||
# Include any configuration or setups specific to search tests here
|
||||
end
|
||||
|
||||
require File.expand_path('../config/environment', __dir__)
|
||||
|
||||
abort('The Rails environment is running in production mode!') if Rails.env.production?
|
||||
|
@ -35,8 +31,6 @@ Sidekiq.logger = nil
|
|||
|
||||
# System tests config
|
||||
DatabaseCleaner.strategy = [:deletion]
|
||||
streaming_server_manager = StreamingServerManager.new
|
||||
search_data_manager = SearchDataManager.new
|
||||
|
||||
Devise::Test::ControllerHelpers.module_eval do
|
||||
alias_method :original_sign_in, :sign_in
|
||||
|
@ -100,26 +94,7 @@ RSpec.configure do |config|
|
|||
Capybara.current_driver = :rack_test
|
||||
end
|
||||
|
||||
config.before :suite do
|
||||
if RUN_SYSTEM_SPECS
|
||||
Webpacker.compile
|
||||
streaming_server_manager.start(port: STREAMING_PORT)
|
||||
end
|
||||
|
||||
if RUN_SEARCH_SPECS
|
||||
Chewy.strategy(:urgent)
|
||||
search_data_manager.prepare_test_data
|
||||
end
|
||||
end
|
||||
|
||||
config.after :suite do
|
||||
streaming_server_manager.stop
|
||||
|
||||
search_data_manager.cleanup_test_data if RUN_SEARCH_SPECS
|
||||
end
|
||||
|
||||
config.around :each, type: :system do |example|
|
||||
# driven_by :selenium, using: :chrome, screen_size: [1600, 1200]
|
||||
driven_by :selenium, using: :headless_chrome, screen_size: [1600, 1200]
|
||||
|
||||
# The streaming server needs access to the database
|
||||
|
@ -136,12 +111,6 @@ RSpec.configure do |config|
|
|||
self.use_transactional_tests = true
|
||||
end
|
||||
|
||||
config.around :each, type: :search do |example|
|
||||
search_data_manager.populate_indexes
|
||||
example.run
|
||||
search_data_manager.remove_indexes
|
||||
end
|
||||
|
||||
config.before do |example|
|
||||
unless example.metadata[:paperclip_processing]
|
||||
allow_any_instance_of(Paperclip::Attachment).to receive(:post_process).and_return(true) # rubocop:disable RSpec/AnyInstance
|
||||
|
|
|
@ -119,40 +119,39 @@ module TestEndpoints
|
|||
end
|
||||
|
||||
describe 'Caching behavior' do
|
||||
shared_examples 'cachable response' do
|
||||
it 'does not set cookies' do
|
||||
shared_examples 'cachable response' do |http_success: false|
|
||||
it 'does not set cookies or set public cache control', :aggregate_failures do
|
||||
expect(response.cookies).to be_empty
|
||||
end
|
||||
|
||||
it 'sets public cache control' do
|
||||
# expect(response.cache_control[:max_age]&.to_i).to be_positive
|
||||
expect(response.cache_control[:public]).to be_truthy
|
||||
expect(response.cache_control[:private]).to be_falsy
|
||||
expect(response.cache_control[:no_store]).to be_falsy
|
||||
expect(response.cache_control[:no_cache]).to be_falsy
|
||||
|
||||
expect(response).to have_http_status(200) if http_success
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'non-cacheable response' do
|
||||
shared_examples 'non-cacheable response' do |http_success: false|
|
||||
it 'sets private cache control' do
|
||||
expect(response.cache_control[:private]).to be_truthy
|
||||
expect(response.cache_control[:no_store]).to be_truthy
|
||||
|
||||
expect(response).to have_http_status(200) if http_success
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'non-cacheable error' do
|
||||
it 'does not return HTTP success' do
|
||||
it 'does not return HTTP success and does not have cache headers', :aggregate_failures do
|
||||
expect(response).to_not have_http_status(200)
|
||||
end
|
||||
|
||||
it 'does not have cache headers' do
|
||||
expect(response.cache_control[:public]).to be_falsy
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'language-dependent' do
|
||||
it 'has a Vary on Accept-Language' do
|
||||
expect(response.headers['Vary']&.split(',')&.map { |x| x.strip.downcase }).to include('accept-language')
|
||||
expect(response_vary_headers).to include('accept-language')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -180,6 +179,15 @@ describe 'Caching behavior' do
|
|||
end
|
||||
|
||||
context 'when anonymously accessed' do
|
||||
describe '/users/alice' do
|
||||
it 'redirects with proper cache header', :aggregate_failures do
|
||||
get '/users/alice'
|
||||
|
||||
expect(response).to redirect_to('/@alice')
|
||||
expect(response.headers['Vary']&.split(',')&.map { |x| x.strip.downcase }).to include('accept')
|
||||
end
|
||||
end
|
||||
|
||||
TestEndpoints::ALWAYS_CACHED.each do |endpoint|
|
||||
describe endpoint do
|
||||
before { get endpoint }
|
||||
|
@ -196,7 +204,7 @@ describe 'Caching behavior' do
|
|||
it_behaves_like 'cachable response'
|
||||
|
||||
it 'has a Vary on Cookie' do
|
||||
expect(response.headers['Vary']&.split(',')&.map { |x| x.strip.downcase }).to include('cookie')
|
||||
expect(response_vary_headers).to include('cookie')
|
||||
end
|
||||
|
||||
it_behaves_like 'language-dependent' if TestEndpoints::LANGUAGE_DEPENDENT.include?(endpoint)
|
||||
|
@ -210,7 +218,7 @@ describe 'Caching behavior' do
|
|||
it_behaves_like 'cachable response'
|
||||
|
||||
it 'has a Vary on Authorization' do
|
||||
expect(response.headers['Vary']&.split(',')&.map { |x| x.strip.downcase }).to include('authorization')
|
||||
expect(response_vary_headers).to include('authorization')
|
||||
end
|
||||
|
||||
it_behaves_like 'language-dependent' if TestEndpoints::LANGUAGE_DEPENDENT.include?(endpoint)
|
||||
|
@ -296,7 +304,7 @@ describe 'Caching behavior' do
|
|||
it_behaves_like 'non-cacheable response'
|
||||
|
||||
it 'has a Vary on Cookie' do
|
||||
expect(response.headers['Vary']&.split(',')&.map { |x| x.strip.downcase }).to include('cookie')
|
||||
expect(response_vary_headers).to include('cookie')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -305,11 +313,7 @@ describe 'Caching behavior' do
|
|||
describe endpoint do
|
||||
before { get endpoint }
|
||||
|
||||
it_behaves_like 'non-cacheable response'
|
||||
|
||||
it 'returns HTTP success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
it_behaves_like 'non-cacheable response', http_success: true
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -345,7 +349,7 @@ describe 'Caching behavior' do
|
|||
it_behaves_like 'non-cacheable response'
|
||||
|
||||
it 'has a Vary on Authorization' do
|
||||
expect(response.headers['Vary']&.split(',')&.map { |x| x.strip.downcase }).to include('authorization')
|
||||
expect(response_vary_headers).to include('authorization')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -356,11 +360,7 @@ describe 'Caching behavior' do
|
|||
get endpoint, headers: { 'Authorization' => "Bearer #{token.token}" }
|
||||
end
|
||||
|
||||
it_behaves_like 'non-cacheable response'
|
||||
|
||||
it 'returns HTTP success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
it_behaves_like 'non-cacheable response', http_success: true
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -387,11 +387,7 @@ describe 'Caching behavior' do
|
|||
context 'when allowed for local users only' do
|
||||
let(:show_domain_blocks) { 'users' }
|
||||
|
||||
it_behaves_like 'non-cacheable response'
|
||||
|
||||
it 'returns HTTP success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
it_behaves_like 'non-cacheable response', http_success: true
|
||||
end
|
||||
|
||||
context 'when disabled' do
|
||||
|
@ -415,11 +411,7 @@ describe 'Caching behavior' do
|
|||
get '/actor', sign_with: remote_actor, headers: { 'Accept' => 'application/activity+json' }
|
||||
end
|
||||
|
||||
it_behaves_like 'cachable response'
|
||||
|
||||
it 'returns HTTP success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
it_behaves_like 'cachable response', http_success: true
|
||||
end
|
||||
|
||||
TestEndpoints::REQUIRE_SIGNATURE.each do |endpoint|
|
||||
|
@ -428,11 +420,7 @@ describe 'Caching behavior' do
|
|||
get endpoint, sign_with: remote_actor, headers: { 'Accept' => 'application/activity+json' }
|
||||
end
|
||||
|
||||
it_behaves_like 'non-cacheable response'
|
||||
|
||||
it 'returns HTTP success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
it_behaves_like 'non-cacheable response', http_success: true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -450,11 +438,7 @@ describe 'Caching behavior' do
|
|||
get '/actor', headers: { 'Accept' => 'application/activity+json' }
|
||||
end
|
||||
|
||||
it_behaves_like 'cachable response'
|
||||
|
||||
it 'returns HTTP success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
it_behaves_like 'cachable response', http_success: true
|
||||
end
|
||||
|
||||
(TestEndpoints::REQUIRE_SIGNATURE + TestEndpoints::AuthorizedFetch::REQUIRE_SIGNATURE).each do |endpoint|
|
||||
|
@ -481,11 +465,7 @@ describe 'Caching behavior' do
|
|||
get '/actor', sign_with: remote_actor, headers: { 'Accept' => 'application/activity+json' }
|
||||
end
|
||||
|
||||
it_behaves_like 'cachable response'
|
||||
|
||||
it 'returns HTTP success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
it_behaves_like 'cachable response', http_success: true
|
||||
end
|
||||
|
||||
(TestEndpoints::REQUIRE_SIGNATURE + TestEndpoints::AuthorizedFetch::REQUIRE_SIGNATURE).each do |endpoint|
|
||||
|
@ -494,11 +474,7 @@ describe 'Caching behavior' do
|
|||
get endpoint, sign_with: remote_actor, headers: { 'Accept' => 'application/activity+json' }
|
||||
end
|
||||
|
||||
it_behaves_like 'non-cacheable response'
|
||||
|
||||
it 'returns HTTP success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
it_behaves_like 'non-cacheable response', http_success: true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -522,11 +498,7 @@ describe 'Caching behavior' do
|
|||
get '/actor', headers: { 'Accept' => 'application/activity+json' }
|
||||
end
|
||||
|
||||
it_behaves_like 'cachable response'
|
||||
|
||||
it 'returns HTTP success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
it_behaves_like 'cachable response', http_success: true
|
||||
end
|
||||
|
||||
(TestEndpoints::REQUIRE_SIGNATURE + TestEndpoints::AuthorizedFetch::REQUIRE_SIGNATURE).each do |endpoint|
|
||||
|
@ -554,11 +526,7 @@ describe 'Caching behavior' do
|
|||
get '/actor', sign_with: remote_actor, headers: { 'Accept' => 'application/activity+json' }
|
||||
end
|
||||
|
||||
it_behaves_like 'cachable response'
|
||||
|
||||
it 'returns HTTP success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
it_behaves_like 'cachable response', http_success: true
|
||||
end
|
||||
|
||||
(TestEndpoints::REQUIRE_SIGNATURE + TestEndpoints::AuthorizedFetch::REQUIRE_SIGNATURE).each do |endpoint|
|
||||
|
@ -567,11 +535,7 @@ describe 'Caching behavior' do
|
|||
get endpoint, sign_with: remote_actor, headers: { 'Accept' => 'application/activity+json' }
|
||||
end
|
||||
|
||||
it_behaves_like 'non-cacheable response'
|
||||
|
||||
it 'returns HTTP success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
it_behaves_like 'non-cacheable response', http_success: true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -585,11 +549,7 @@ describe 'Caching behavior' do
|
|||
get '/actor', sign_with: remote_actor, headers: { 'Accept' => 'application/activity+json' }
|
||||
end
|
||||
|
||||
it_behaves_like 'cachable response'
|
||||
|
||||
it 'returns HTTP success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
it_behaves_like 'cachable response', http_success: true
|
||||
end
|
||||
|
||||
(TestEndpoints::REQUIRE_SIGNATURE + TestEndpoints::AuthorizedFetch::REQUIRE_SIGNATURE).each do |endpoint|
|
||||
|
@ -661,7 +621,7 @@ describe 'Caching behavior' do
|
|||
it_behaves_like 'non-cacheable response'
|
||||
|
||||
it 'has a Vary on Authorization' do
|
||||
expect(response.headers['Vary']&.split(',')&.map { |x| x.strip.downcase }).to include('authorization')
|
||||
expect(response_vary_headers).to include('authorization')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -672,13 +632,15 @@ describe 'Caching behavior' do
|
|||
get endpoint, headers: { 'Authorization' => "Bearer #{token.token}" }
|
||||
end
|
||||
|
||||
it_behaves_like 'non-cacheable response'
|
||||
|
||||
it 'returns HTTP success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
it_behaves_like 'non-cacheable response', http_success: true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def response_vary_headers
|
||||
response.headers['Vary']&.split(',')&.map { |x| x.strip.downcase }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,71 +20,70 @@ RSpec.describe RemoveStatusService, type: :service do
|
|||
end
|
||||
|
||||
context 'when removed status is not a reblog' do
|
||||
let!(:status) { PostStatusService.new.call(alice, text: 'Hello @bob@example.com ThisIsASecret') }
|
||||
|
||||
before do
|
||||
@status = PostStatusService.new.call(alice, text: 'Hello @bob@example.com ThisIsASecret')
|
||||
FavouriteService.new.call(jeff, @status)
|
||||
Fabricate(:status, account: bill, reblog: @status, uri: 'hoge')
|
||||
FavouriteService.new.call(jeff, status)
|
||||
Fabricate(:status, account: bill, reblog: status, uri: 'hoge')
|
||||
end
|
||||
|
||||
it 'removes status from author\'s home feed' do
|
||||
subject.call(@status)
|
||||
expect(HomeFeed.new(alice).get(10).pluck(:id)).to_not include(@status.id)
|
||||
subject.call(status)
|
||||
expect(HomeFeed.new(alice).get(10).pluck(:id)).to_not include(status.id)
|
||||
end
|
||||
|
||||
it 'removes status from local follower\'s home feed' do
|
||||
subject.call(@status)
|
||||
expect(HomeFeed.new(jeff).get(10).pluck(:id)).to_not include(@status.id)
|
||||
subject.call(status)
|
||||
expect(HomeFeed.new(jeff).get(10).pluck(:id)).to_not include(status.id)
|
||||
end
|
||||
|
||||
it 'sends Delete activity to followers' do
|
||||
subject.call(@status)
|
||||
subject.call(status)
|
||||
expect(a_request(:post, 'http://example.com/inbox').with(
|
||||
body: hash_including({
|
||||
'type' => 'Delete',
|
||||
'object' => {
|
||||
'type' => 'Tombstone',
|
||||
'id' => ActivityPub::TagManager.instance.uri_for(@status),
|
||||
'atomUri' => OStatus::TagManager.instance.uri_for(@status),
|
||||
'id' => ActivityPub::TagManager.instance.uri_for(status),
|
||||
'atomUri' => OStatus::TagManager.instance.uri_for(status),
|
||||
},
|
||||
})
|
||||
)).to have_been_made.once
|
||||
end
|
||||
|
||||
it 'sends Delete activity to rebloggers' do
|
||||
subject.call(@status)
|
||||
subject.call(status)
|
||||
expect(a_request(:post, 'http://example2.com/inbox').with(
|
||||
body: hash_including({
|
||||
'type' => 'Delete',
|
||||
'object' => {
|
||||
'type' => 'Tombstone',
|
||||
'id' => ActivityPub::TagManager.instance.uri_for(@status),
|
||||
'atomUri' => OStatus::TagManager.instance.uri_for(@status),
|
||||
'id' => ActivityPub::TagManager.instance.uri_for(status),
|
||||
'atomUri' => OStatus::TagManager.instance.uri_for(status),
|
||||
},
|
||||
})
|
||||
)).to have_been_made.once
|
||||
end
|
||||
|
||||
it 'remove status from notifications' do
|
||||
expect { subject.call(@status) }.to change {
|
||||
expect { subject.call(status) }.to change {
|
||||
Notification.where(activity_type: 'Favourite', from_account: jeff, account: alice).count
|
||||
}.from(1).to(0)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when removed status is a private self-reblog' do
|
||||
before do
|
||||
@original_status = Fabricate(:status, account: alice, text: 'Hello ThisIsASecret', visibility: :private)
|
||||
@status = ReblogService.new.call(alice, @original_status)
|
||||
end
|
||||
let!(:original_status) { Fabricate(:status, account: alice, text: 'Hello ThisIsASecret', visibility: :private) }
|
||||
let!(:status) { ReblogService.new.call(alice, original_status) }
|
||||
|
||||
it 'sends Undo activity to followers' do
|
||||
subject.call(@status)
|
||||
subject.call(status)
|
||||
expect(a_request(:post, 'http://example.com/inbox').with(
|
||||
body: hash_including({
|
||||
'type' => 'Undo',
|
||||
'object' => hash_including({
|
||||
'type' => 'Announce',
|
||||
'object' => ActivityPub::TagManager.instance.uri_for(@original_status),
|
||||
'object' => ActivityPub::TagManager.instance.uri_for(original_status),
|
||||
}),
|
||||
})
|
||||
)).to have_been_made.once
|
||||
|
@ -92,19 +91,17 @@ RSpec.describe RemoveStatusService, type: :service do
|
|||
end
|
||||
|
||||
context 'when removed status is public self-reblog' do
|
||||
before do
|
||||
@original_status = Fabricate(:status, account: alice, text: 'Hello ThisIsASecret', visibility: :public)
|
||||
@status = ReblogService.new.call(alice, @original_status)
|
||||
end
|
||||
let!(:original_status) { Fabricate(:status, account: alice, text: 'Hello ThisIsASecret', visibility: :public) }
|
||||
let!(:status) { ReblogService.new.call(alice, original_status) }
|
||||
|
||||
it 'sends Undo activity to followers' do
|
||||
subject.call(@status)
|
||||
subject.call(status)
|
||||
expect(a_request(:post, 'http://example.com/inbox').with(
|
||||
body: hash_including({
|
||||
'type' => 'Undo',
|
||||
'object' => hash_including({
|
||||
'type' => 'Announce',
|
||||
'object' => ActivityPub::TagManager.instance.uri_for(@original_status),
|
||||
'object' => ActivityPub::TagManager.instance.uri_for(original_status),
|
||||
}),
|
||||
})
|
||||
)).to have_been_made.once
|
||||
|
|
|
@ -19,17 +19,15 @@ describe SearchService, type: :service do
|
|||
end
|
||||
|
||||
describe 'with an url query' do
|
||||
before do
|
||||
@query = 'http://test.host/query'
|
||||
end
|
||||
let(:query) { 'http://test.host/query' }
|
||||
|
||||
context 'when it does not find anything' do
|
||||
it 'returns the empty results' do
|
||||
service = instance_double(ResolveURLService, call: nil)
|
||||
allow(ResolveURLService).to receive(:new).and_return(service)
|
||||
results = subject.call(@query, nil, 10, resolve: true)
|
||||
results = subject.call(query, nil, 10, resolve: true)
|
||||
|
||||
expect(service).to have_received(:call).with(@query, on_behalf_of: nil)
|
||||
expect(service).to have_received(:call).with(query, on_behalf_of: nil)
|
||||
expect(results).to eq empty_results
|
||||
end
|
||||
end
|
||||
|
@ -40,8 +38,8 @@ describe SearchService, type: :service do
|
|||
service = instance_double(ResolveURLService, call: account)
|
||||
allow(ResolveURLService).to receive(:new).and_return(service)
|
||||
|
||||
results = subject.call(@query, nil, 10, resolve: true)
|
||||
expect(service).to have_received(:call).with(@query, on_behalf_of: nil)
|
||||
results = subject.call(query, nil, 10, resolve: true)
|
||||
expect(service).to have_received(:call).with(query, on_behalf_of: nil)
|
||||
expect(results).to eq empty_results.merge(accounts: [account])
|
||||
end
|
||||
end
|
||||
|
@ -52,8 +50,8 @@ describe SearchService, type: :service do
|
|||
service = instance_double(ResolveURLService, call: status)
|
||||
allow(ResolveURLService).to receive(:new).and_return(service)
|
||||
|
||||
results = subject.call(@query, nil, 10, resolve: true)
|
||||
expect(service).to have_received(:call).with(@query, on_behalf_of: nil)
|
||||
results = subject.call(query, nil, 10, resolve: true)
|
||||
expect(service).to have_received(:call).with(query, on_behalf_of: nil)
|
||||
expect(results).to eq empty_results.merge(statuses: [status])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,38 +6,36 @@ describe UnblockDomainService, type: :service do
|
|||
subject { described_class.new }
|
||||
|
||||
describe 'call' do
|
||||
before do
|
||||
@independently_suspended = Fabricate(:account, domain: 'example.com', suspended_at: 1.hour.ago)
|
||||
@independently_silenced = Fabricate(:account, domain: 'example.com', silenced_at: 1.hour.ago)
|
||||
@domain_block = Fabricate(:domain_block, domain: 'example.com')
|
||||
@silenced = Fabricate(:account, domain: 'example.com', silenced_at: @domain_block.created_at)
|
||||
@suspended = Fabricate(:account, domain: 'example.com', suspended_at: @domain_block.created_at)
|
||||
end
|
||||
let!(:independently_suspended) { Fabricate(:account, domain: 'example.com', suspended_at: 1.hour.ago) }
|
||||
let!(:independently_silenced) { Fabricate(:account, domain: 'example.com', silenced_at: 1.hour.ago) }
|
||||
let!(:domain_block) { Fabricate(:domain_block, domain: 'example.com') }
|
||||
let!(:silenced) { Fabricate(:account, domain: 'example.com', silenced_at: domain_block.created_at) }
|
||||
let!(:suspended) { Fabricate(:account, domain: 'example.com', suspended_at: domain_block.created_at) }
|
||||
|
||||
it 'unsilences accounts and removes block' do
|
||||
@domain_block.update(severity: :silence)
|
||||
domain_block.update(severity: :silence)
|
||||
|
||||
subject.call(@domain_block)
|
||||
subject.call(domain_block)
|
||||
expect_deleted_domain_block
|
||||
expect(@silenced.reload.silenced?).to be false
|
||||
expect(@suspended.reload.suspended?).to be true
|
||||
expect(@independently_suspended.reload.suspended?).to be true
|
||||
expect(@independently_silenced.reload.silenced?).to be true
|
||||
expect(silenced.reload.silenced?).to be false
|
||||
expect(suspended.reload.suspended?).to be true
|
||||
expect(independently_suspended.reload.suspended?).to be true
|
||||
expect(independently_silenced.reload.silenced?).to be true
|
||||
end
|
||||
|
||||
it 'unsuspends accounts and removes block' do
|
||||
@domain_block.update(severity: :suspend)
|
||||
domain_block.update(severity: :suspend)
|
||||
|
||||
subject.call(@domain_block)
|
||||
subject.call(domain_block)
|
||||
expect_deleted_domain_block
|
||||
expect(@suspended.reload.suspended?).to be false
|
||||
expect(@silenced.reload.silenced?).to be false
|
||||
expect(@independently_suspended.reload.suspended?).to be true
|
||||
expect(@independently_silenced.reload.silenced?).to be true
|
||||
expect(suspended.reload.suspended?).to be false
|
||||
expect(silenced.reload.silenced?).to be false
|
||||
expect(independently_suspended.reload.suspended?).to be true
|
||||
expect(independently_silenced.reload.silenced?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
def expect_deleted_domain_block
|
||||
expect { @domain_block.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
expect { domain_block.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -41,3 +41,38 @@ class SearchDataManager
|
|||
Tag.destroy_all
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.before :suite do
|
||||
if search_examples_present?
|
||||
# Configure chewy to use `urgent` strategy to index documents
|
||||
Chewy.strategy(:urgent)
|
||||
|
||||
# Create search data
|
||||
search_data_manager.prepare_test_data
|
||||
end
|
||||
end
|
||||
|
||||
config.after :suite do
|
||||
if search_examples_present?
|
||||
# Clean up after search data
|
||||
search_data_manager.cleanup_test_data
|
||||
end
|
||||
end
|
||||
|
||||
config.around :each, type: :search do |example|
|
||||
search_data_manager.populate_indexes
|
||||
example.run
|
||||
search_data_manager.remove_indexes
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def search_data_manager
|
||||
@search_data_manager ||= SearchDataManager.new
|
||||
end
|
||||
|
||||
def search_examples_present?
|
||||
RUN_SEARCH_SPECS
|
||||
end
|
||||
end
|
||||
|
|
|
@ -76,3 +76,32 @@ class StreamingServerManager
|
|||
@running_thread.join
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.before :suite do
|
||||
if streaming_examples_present?
|
||||
# Compile assets
|
||||
Webpacker.compile
|
||||
|
||||
# Start the node streaming server
|
||||
streaming_server_manager.start(port: STREAMING_PORT)
|
||||
end
|
||||
end
|
||||
|
||||
config.after :suite do
|
||||
if streaming_examples_present?
|
||||
# Stop the node streaming server
|
||||
streaming_server_manager.stop
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def streaming_server_manager
|
||||
@streaming_server_manager ||= StreamingServerManager.new
|
||||
end
|
||||
|
||||
def streaming_examples_present?
|
||||
RUN_SYSTEM_SPECS
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe BlacklistedEmailValidator, type: :validator do
|
||||
RSpec.describe BlacklistedEmailValidator do
|
||||
describe '#validate' do
|
||||
subject { described_class.new.validate(user); errors }
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe DisallowedHashtagsValidator, type: :validator do
|
||||
RSpec.describe DisallowedHashtagsValidator do
|
||||
let(:disallowed_tags) { [] }
|
||||
|
||||
describe '#validate' do
|
||||
|
|
|
@ -2,48 +2,76 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe FollowLimitValidator, type: :validator do
|
||||
RSpec.describe FollowLimitValidator do
|
||||
describe '#validate' do
|
||||
before do
|
||||
allow_any_instance_of(described_class).to receive(:limit_reached?).with(account) do
|
||||
limit_reached
|
||||
end
|
||||
context 'with a nil account' do
|
||||
it 'does not add validation errors to base' do
|
||||
follow = Fabricate.build(:follow, account: nil)
|
||||
|
||||
described_class.new.validate(follow)
|
||||
end
|
||||
follow.valid?
|
||||
|
||||
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 }
|
||||
|
||||
context 'with follow.account.nil? || !follow.account.local?' do
|
||||
let(:_nil) { true }
|
||||
|
||||
it 'not calls errors.add' do
|
||||
expect(errors).to_not have_received(:add).with(:base, any_args)
|
||||
expect(follow.errors[:base]).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'with !(follow.account.nil? || !follow.account.local?)' do
|
||||
let(:_nil) { false }
|
||||
let(:local) { true }
|
||||
context 'with a non-local account' do
|
||||
it 'does not add validation errors to base' do
|
||||
follow = Fabricate.build(:follow, account: Account.new(domain: 'host.example'))
|
||||
|
||||
context 'when limit_reached?' do
|
||||
let(:limit_reached) { true }
|
||||
follow.valid?
|
||||
|
||||
it 'calls errors.add' do
|
||||
expect(errors).to have_received(:add)
|
||||
.with(:base, I18n.t('users.follow_limit_reached', limit: FollowLimitValidator::LIMIT))
|
||||
expect(follow.errors[:base]).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a local account' do
|
||||
let(:account) { Account.new }
|
||||
|
||||
context 'when the followers count is under the limit' do
|
||||
before do
|
||||
allow(account).to receive(:following_count).and_return(described_class::LIMIT - 100)
|
||||
end
|
||||
|
||||
it 'does not add validation errors to base' do
|
||||
follow = Fabricate.build(:follow, account: account)
|
||||
|
||||
follow.valid?
|
||||
|
||||
expect(follow.errors[:base]).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'with !limit_reached?' do
|
||||
let(:limit_reached) { false }
|
||||
context 'when the following count is over the limit' do
|
||||
before do
|
||||
allow(account).to receive(:following_count).and_return(described_class::LIMIT + 100)
|
||||
end
|
||||
|
||||
it 'not calls errors.add' do
|
||||
expect(errors).to_not have_received(:add).with(:base, any_args)
|
||||
context 'when the followers count is low' do
|
||||
before do
|
||||
allow(account).to receive(:followers_count).and_return(10)
|
||||
end
|
||||
|
||||
it 'adds validation errors to base' do
|
||||
follow = Fabricate.build(:follow, account: account)
|
||||
|
||||
follow.valid?
|
||||
|
||||
expect(follow.errors[:base]).to include(I18n.t('users.follow_limit_reached', limit: FollowLimitValidator::LIMIT))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the followers count is high' do
|
||||
before do
|
||||
allow(account).to receive(:followers_count).and_return(100_000)
|
||||
end
|
||||
|
||||
it 'does not add validation errors to base' do
|
||||
follow = Fabricate.build(:follow, account: account)
|
||||
|
||||
follow.valid?
|
||||
|
||||
expect(follow.errors[:base]).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe PollValidator, type: :validator do
|
||||
RSpec.describe PollValidator do
|
||||
describe '#validate' do
|
||||
before do
|
||||
validator.validate(poll)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe StatusPinValidator, type: :validator do
|
||||
RSpec.describe StatusPinValidator do
|
||||
describe '#validate' do
|
||||
before do
|
||||
subject.validate(pin)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue