mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-26 20:36:25 +00:00
Merge commit 'f99e05710ea06cf10bbd3fb64ae8c00b095cb455' into glitch-soc/merge-upstream
Conflicts: - `.rubocop_todo.yml`: Took upstream's version of the conflicting lines.
This commit is contained in:
@@ -123,7 +123,7 @@ RSpec.describe ActivityPub::RepliesController do
|
||||
end
|
||||
|
||||
it 'uses ids for remote toots' do
|
||||
remote_replies = page_json[:items].select { |x| !x.is_a?(Hash) }
|
||||
remote_replies = page_json[:items].reject { |x| x.is_a?(Hash) }
|
||||
expect(remote_replies.all? { |item| item.is_a?(String) && !ActivityPub::TagManager.instance.local_uri?(item) }).to be true
|
||||
end
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ require 'rails_helper'
|
||||
describe EmojisController do
|
||||
render_views
|
||||
|
||||
let(:emoji) { Fabricate(:custom_emoji) }
|
||||
let(:emoji) { Fabricate(:custom_emoji, shortcode: 'coolcat') }
|
||||
|
||||
describe 'GET #show' do
|
||||
let(:response) { get :show, params: { id: emoji.id, format: :json } }
|
||||
|
||||
@@ -194,60 +194,49 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
|
||||
add_webauthn_credential(user)
|
||||
end
|
||||
|
||||
context 'when creation succeeds' do
|
||||
it 'adds a new credential to user credentials and does not change webauthn_id', :aggregate_failures do
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
|
||||
expect do
|
||||
post :create, params: { credential: new_webauthn_credential, nickname: nickname }
|
||||
end.to change { user.webauthn_credentials.count }.by(1)
|
||||
.and not_change(user, :webauthn_id)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the nickname is already used' do
|
||||
it 'fails' do
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
|
||||
post :create, params: { credential: new_webauthn_credential, nickname: 'USB Key' }
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
expect(flash[:error]).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the credential already exists' do
|
||||
before do
|
||||
user2 = Fabricate(:user)
|
||||
public_key_credential = WebAuthn::Credential.from_create(new_webauthn_credential)
|
||||
Fabricate(:webauthn_credential,
|
||||
user_id: user2.id,
|
||||
external_id: public_key_credential.id,
|
||||
public_key: public_key_credential.public_key)
|
||||
end
|
||||
|
||||
it 'fails' do
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
it 'adds a new credential to user credentials and does not change webauthn_id when creation succeeds', :aggregate_failures do
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
|
||||
expect do
|
||||
post :create, params: { credential: new_webauthn_credential, nickname: nickname }
|
||||
end.to change { user.webauthn_credentials.count }.by(1)
|
||||
.and not_change(user, :webauthn_id)
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
expect(flash[:error]).to be_present
|
||||
end
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'fails when the nickname is already used' do
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
|
||||
post :create, params: { credential: new_webauthn_credential, nickname: 'USB Key' }
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
expect(flash[:error]).to be_present
|
||||
end
|
||||
|
||||
it 'fails when the credential already exists' do
|
||||
public_key_credential = WebAuthn::Credential.from_create(new_webauthn_credential)
|
||||
Fabricate(:webauthn_credential,
|
||||
user_id: Fabricate(:user).id,
|
||||
external_id: public_key_credential.id,
|
||||
public_key: public_key_credential.public_key)
|
||||
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
|
||||
post :create, params: { credential: new_webauthn_credential, nickname: nickname }
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
expect(flash[:error]).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user have not enabled webauthn' do
|
||||
context 'when creation succeeds' do
|
||||
it 'creates a webauthn credential' do
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
context 'when user have not enabled webauthn and creation succeeds' do
|
||||
it 'creates a webauthn credential' do
|
||||
controller.session[:webauthn_challenge] = challenge
|
||||
|
||||
expect do
|
||||
post :create, params: { credential: new_webauthn_credential, nickname: nickname }
|
||||
end.to change { user.webauthn_credentials.count }.by(1)
|
||||
end
|
||||
expect do
|
||||
post :create, params: { credential: new_webauthn_credential, nickname: nickname }
|
||||
end.to change { user.webauthn_credentials.count }.by(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -292,15 +281,13 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
|
||||
add_webauthn_credential(user)
|
||||
end
|
||||
|
||||
context 'when deletion succeeds' do
|
||||
it 'redirects to 2FA methods list and shows flash success and deletes the credential', :aggregate_failures do
|
||||
expect do
|
||||
delete :destroy, params: { id: user.webauthn_credentials.take.id }
|
||||
end.to change { user.webauthn_credentials.count }.by(-1)
|
||||
it 'redirects to 2FA methods list and shows flash success and deletes the credential when deletion succeeds', :aggregate_failures do
|
||||
expect do
|
||||
delete :destroy, params: { id: user.webauthn_credentials.take.id }
|
||||
end.to change { user.webauthn_credentials.count }.by(-1)
|
||||
|
||||
expect(response).to redirect_to settings_two_factor_authentication_methods_path
|
||||
expect(flash[:success]).to be_present
|
||||
end
|
||||
expect(response).to redirect_to settings_two_factor_authentication_methods_path
|
||||
expect(flash[:success]).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
6
spec/fabricators/announcement_mute_fabricator.rb
Normal file
6
spec/fabricators/announcement_mute_fabricator.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Fabricator(:announcement_mute) do
|
||||
announcement { Fabricate.build(:announcement) }
|
||||
account { Fabricate.build(:account) }
|
||||
end
|
||||
7
spec/fabricators/announcement_reaction_fabricator.rb
Normal file
7
spec/fabricators/announcement_reaction_fabricator.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Fabricator(:announcement_reaction) do
|
||||
account { Fabricate.build(:account) }
|
||||
announcement { Fabricate.build(:announcement) }
|
||||
name { Fabricate(:custom_emoji).shortcode }
|
||||
end
|
||||
@@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Fabricator(:custom_emoji) do
|
||||
shortcode 'coolcat'
|
||||
shortcode { sequence(:shortcode) { |i| "code_#{i}" } }
|
||||
domain nil
|
||||
image { Rails.root.join('spec', 'fixtures', 'files', 'emojo.png').open }
|
||||
end
|
||||
|
||||
@@ -77,7 +77,8 @@ describe Mastodon::CLI::Accounts do
|
||||
it_behaves_like 'a new user with given email address and username'
|
||||
|
||||
it 'creates a new user with confirmed status' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('New password')
|
||||
|
||||
user = User.find_by(email: options[:email])
|
||||
|
||||
@@ -95,7 +96,8 @@ describe Mastodon::CLI::Accounts do
|
||||
it_behaves_like 'a new user with given email address and username'
|
||||
|
||||
it 'creates a new user with approved status' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('New password')
|
||||
|
||||
user = User.find_by(email: options[:email])
|
||||
|
||||
@@ -111,7 +113,8 @@ describe Mastodon::CLI::Accounts do
|
||||
it_behaves_like 'a new user with given email address and username'
|
||||
|
||||
it 'creates a new user and assigns the specified role' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('New password')
|
||||
|
||||
role = User.find_by(email: options[:email])&.role
|
||||
|
||||
@@ -148,7 +151,8 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:options) { { email: 'tootctl_new@example.com', reattach: true, force: true } }
|
||||
|
||||
it 'reattaches the account to the new user and deletes the previous user' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('New password')
|
||||
|
||||
user = Account.find_local('tootctl_username')&.user
|
||||
|
||||
@@ -220,7 +224,8 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:options) { { role: default_role.name } }
|
||||
|
||||
it "updates the user's role to the specified role" do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
role = user.reload.role
|
||||
|
||||
@@ -235,7 +240,8 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:user) { Fabricate(:user, role: role) }
|
||||
|
||||
it "removes the user's role successfully" do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
role = user.reload.role
|
||||
|
||||
@@ -248,13 +254,15 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:options) { { email: 'new_email@email.com' } }
|
||||
|
||||
it "sets the user's unconfirmed email to the provided email address" do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(user.reload.unconfirmed_email).to eq(options[:email])
|
||||
end
|
||||
|
||||
it "does not update the user's original email address" do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(user.reload.email).to eq('old_email@email.com')
|
||||
end
|
||||
@@ -264,13 +272,15 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:options) { { email: 'new_email@email.com', confirm: true } }
|
||||
|
||||
it "updates the user's email address to the provided email" do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(user.reload.email).to eq(options[:email])
|
||||
end
|
||||
|
||||
it "sets the user's email address as confirmed" do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(user.reload.confirmed?).to be(true)
|
||||
end
|
||||
@@ -282,7 +292,8 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:options) { { confirm: true } }
|
||||
|
||||
it "confirms the user's email address" do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(user.reload.confirmed?).to be(true)
|
||||
end
|
||||
@@ -297,7 +308,9 @@ describe Mastodon::CLI::Accounts do
|
||||
end
|
||||
|
||||
it 'approves the user' do
|
||||
expect { subject }.to change { user.reload.approved }.from(false).to(true)
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
.and change { user.reload.approved }.from(false).to(true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -306,7 +319,9 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:options) { { disable: true } }
|
||||
|
||||
it 'disables the user' do
|
||||
expect { subject }.to change { user.reload.disabled }.from(false).to(true)
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
.and change { user.reload.disabled }.from(false).to(true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -315,7 +330,9 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:options) { { enable: true } }
|
||||
|
||||
it 'enables the user' do
|
||||
expect { subject }.to change { user.reload.disabled }.from(true).to(false)
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
.and change { user.reload.disabled }.from(true).to(false)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -335,7 +352,9 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:options) { { disable_2fa: true } }
|
||||
|
||||
it 'disables the two-factor authentication for the user' do
|
||||
expect { subject }.to change { user.reload.otp_required_for_login }.from(true).to(false)
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
.and change { user.reload.otp_required_for_login }.from(true).to(false)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -385,7 +404,8 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:arguments) { [account.username] }
|
||||
|
||||
it 'deletes the specified user successfully' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('Deleting')
|
||||
|
||||
expect(delete_account_service).to have_received(:call).with(account, reserve_email: false).once
|
||||
end
|
||||
@@ -415,7 +435,8 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:options) { { email: account.user.email } }
|
||||
|
||||
it 'deletes the specified user successfully' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('Deleting')
|
||||
|
||||
expect(delete_account_service).to have_received(:call).with(account, reserve_email: false).once
|
||||
end
|
||||
@@ -457,7 +478,8 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:options) { { all: true } }
|
||||
|
||||
it 'approves all pending registrations' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(User.pluck(:approved).all?(true)).to be(true)
|
||||
end
|
||||
@@ -468,7 +490,8 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:options) { { number: 2 } }
|
||||
|
||||
it 'approves the earliest n pending registrations but not the remaining ones' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(n_earliest_pending_registrations.all?(&:approved?)).to be(true)
|
||||
expect(pending_registrations.all?(&:approved?)).to be(false)
|
||||
@@ -498,7 +521,7 @@ describe Mastodon::CLI::Accounts do
|
||||
|
||||
it 'approves all users and does not raise any error' do
|
||||
expect { subject }
|
||||
.to_not raise_error
|
||||
.to output_results('OK')
|
||||
expect(User.pluck(:approved).all?(true)).to be(true)
|
||||
end
|
||||
end
|
||||
@@ -510,7 +533,8 @@ describe Mastodon::CLI::Accounts do
|
||||
let(:arguments) { [user.account.username] }
|
||||
|
||||
it 'approves the specified user successfully' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(user.reload.approved?).to be(true)
|
||||
end
|
||||
@@ -655,7 +679,8 @@ describe Mastodon::CLI::Accounts do
|
||||
allow(remote_account_example_com).to receive(:reset_avatar!)
|
||||
allow(account_example_net).to receive(:reset_avatar!)
|
||||
|
||||
cli.refresh
|
||||
expect { cli.refresh }
|
||||
.to output_results('Refreshed 2 accounts')
|
||||
|
||||
expect(cli).to have_received(:parallelize_with_progress).with(scope).once
|
||||
expect(remote_account_example_com).to have_received(:reset_avatar!).once
|
||||
@@ -665,7 +690,8 @@ describe Mastodon::CLI::Accounts do
|
||||
it 'does not refresh avatar for local accounts' do
|
||||
allow(local_account).to receive(:reset_avatar!)
|
||||
|
||||
cli.refresh
|
||||
expect { cli.refresh }
|
||||
.to output_results('Refreshed 2 accounts')
|
||||
|
||||
expect(cli).to have_received(:parallelize_with_progress).with(scope).once
|
||||
expect(local_account).to_not have_received(:reset_avatar!)
|
||||
@@ -675,7 +701,8 @@ describe Mastodon::CLI::Accounts do
|
||||
allow(remote_account_example_com).to receive(:reset_header!)
|
||||
allow(account_example_net).to receive(:reset_header!)
|
||||
|
||||
cli.refresh
|
||||
expect { cli.refresh }
|
||||
.to output_results('Refreshed 2 accounts')
|
||||
|
||||
expect(cli).to have_received(:parallelize_with_progress).with(scope).once
|
||||
expect(remote_account_example_com).to have_received(:reset_header!).once
|
||||
@@ -685,7 +712,8 @@ describe Mastodon::CLI::Accounts do
|
||||
it 'does not refresh the header for local accounts' do
|
||||
allow(local_account).to receive(:reset_header!)
|
||||
|
||||
cli.refresh
|
||||
expect { cli.refresh }
|
||||
.to output_results('Refreshed 2 accounts')
|
||||
|
||||
expect(cli).to have_received(:parallelize_with_progress).with(scope).once
|
||||
expect(local_account).to_not have_received(:reset_header!)
|
||||
@@ -706,7 +734,8 @@ describe Mastodon::CLI::Accounts do
|
||||
allow(remote_account_example_com).to receive(:reset_avatar!)
|
||||
allow(account_example_net).to receive(:reset_avatar!)
|
||||
|
||||
cli.refresh
|
||||
expect { cli.refresh }
|
||||
.to output_results('Refreshed 2 accounts')
|
||||
|
||||
expect(cli).to have_received(:parallelize_with_progress).with(scope).once
|
||||
expect(local_account).to_not have_received(:reset_avatar!)
|
||||
@@ -719,7 +748,8 @@ describe Mastodon::CLI::Accounts do
|
||||
allow(remote_account_example_com).to receive(:reset_header!)
|
||||
allow(account_example_net).to receive(:reset_header!)
|
||||
|
||||
cli.refresh
|
||||
expect { cli.refresh }
|
||||
.to output_results('Refreshed 2 accounts')
|
||||
|
||||
expect(cli).to have_received(:parallelize_with_progress).with(scope).once
|
||||
expect(local_account).to_not have_received(:reset_header!)
|
||||
@@ -752,7 +782,8 @@ describe Mastodon::CLI::Accounts do
|
||||
allow(account_example_com_a).to receive(:reset_avatar!)
|
||||
allow(account_example_com_b).to receive(:reset_avatar!)
|
||||
|
||||
cli.refresh(*arguments)
|
||||
expect { cli.refresh(*arguments) }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(account_example_com_a).to have_received(:reset_avatar!).once
|
||||
expect(account_example_com_b).to have_received(:reset_avatar!).once
|
||||
@@ -761,7 +792,8 @@ describe Mastodon::CLI::Accounts do
|
||||
it 'does not reset the avatar for unspecified accounts' do
|
||||
allow(account_example_net).to receive(:reset_avatar!)
|
||||
|
||||
cli.refresh(*arguments)
|
||||
expect { cli.refresh(*arguments) }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(account_example_net).to_not have_received(:reset_avatar!)
|
||||
end
|
||||
@@ -770,7 +802,8 @@ describe Mastodon::CLI::Accounts do
|
||||
allow(account_example_com_a).to receive(:reset_header!)
|
||||
allow(account_example_com_b).to receive(:reset_header!)
|
||||
|
||||
cli.refresh(*arguments)
|
||||
expect { cli.refresh(*arguments) }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(account_example_com_a).to have_received(:reset_header!).once
|
||||
expect(account_example_com_b).to have_received(:reset_header!).once
|
||||
@@ -779,7 +812,8 @@ describe Mastodon::CLI::Accounts do
|
||||
it 'does not reset the header for unspecified accounts' do
|
||||
allow(account_example_net).to receive(:reset_header!)
|
||||
|
||||
cli.refresh(*arguments)
|
||||
expect { cli.refresh(*arguments) }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(account_example_net).to_not have_received(:reset_header!)
|
||||
end
|
||||
@@ -812,7 +846,8 @@ describe Mastodon::CLI::Accounts do
|
||||
allow(account_example_com_a).to receive(:reset_avatar!)
|
||||
allow(account_example_com_b).to receive(:reset_avatar!)
|
||||
|
||||
cli.refresh(*arguments)
|
||||
expect { cli.refresh(*arguments) }
|
||||
.to output_results('OK (DRY RUN)')
|
||||
|
||||
expect(account_example_com_a).to_not have_received(:reset_avatar!)
|
||||
expect(account_example_com_b).to_not have_received(:reset_avatar!)
|
||||
@@ -822,7 +857,8 @@ describe Mastodon::CLI::Accounts do
|
||||
allow(account_example_com_a).to receive(:reset_header!)
|
||||
allow(account_example_com_b).to receive(:reset_header!)
|
||||
|
||||
cli.refresh(*arguments)
|
||||
expect { cli.refresh(*arguments) }
|
||||
.to output_results('OK (DRY RUN)')
|
||||
|
||||
expect(account_example_com_a).to_not have_received(:reset_header!)
|
||||
expect(account_example_com_b).to_not have_received(:reset_header!)
|
||||
@@ -848,7 +884,8 @@ describe Mastodon::CLI::Accounts do
|
||||
allow(account_example_com_a).to receive(:reset_avatar!)
|
||||
allow(account_example_com_b).to receive(:reset_avatar!)
|
||||
|
||||
cli.refresh
|
||||
expect { cli.refresh }
|
||||
.to output_results('Refreshed 2 accounts')
|
||||
|
||||
expect(cli).to have_received(:parallelize_with_progress).with(scope).once
|
||||
expect(account_example_com_a).to have_received(:reset_avatar!).once
|
||||
@@ -858,7 +895,8 @@ describe Mastodon::CLI::Accounts do
|
||||
it 'does not refresh the avatar for accounts outside specified domain' do
|
||||
allow(account_example_net).to receive(:reset_avatar!)
|
||||
|
||||
cli.refresh
|
||||
expect { cli.refresh }
|
||||
.to output_results('Refreshed 2 accounts')
|
||||
|
||||
expect(cli).to have_received(:parallelize_with_progress).with(scope).once
|
||||
expect(account_example_net).to_not have_received(:reset_avatar!)
|
||||
@@ -868,7 +906,8 @@ describe Mastodon::CLI::Accounts do
|
||||
allow(account_example_com_a).to receive(:reset_header!)
|
||||
allow(account_example_com_b).to receive(:reset_header!)
|
||||
|
||||
cli.refresh
|
||||
expect { cli.refresh }
|
||||
.to output_results('Refreshed 2 accounts')
|
||||
|
||||
expect(cli).to have_received(:parallelize_with_progress).with(scope)
|
||||
expect(account_example_com_a).to have_received(:reset_header!).once
|
||||
@@ -878,7 +917,8 @@ describe Mastodon::CLI::Accounts do
|
||||
it 'does not refresh the header for accounts outside specified domain' do
|
||||
allow(account_example_net).to receive(:reset_header!)
|
||||
|
||||
cli.refresh
|
||||
expect { cli.refresh }
|
||||
.to output_results('Refreshed 2 accounts')
|
||||
|
||||
expect(cli).to have_received(:parallelize_with_progress).with(scope).once
|
||||
expect(account_example_net).to_not have_received(:reset_header!)
|
||||
@@ -913,7 +953,8 @@ describe Mastodon::CLI::Accounts do
|
||||
old_private_key = account.private_key
|
||||
old_public_key = account.public_key
|
||||
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
account.reload
|
||||
|
||||
expect(account.private_key).to_not eq(old_private_key)
|
||||
@@ -923,7 +964,8 @@ describe Mastodon::CLI::Accounts do
|
||||
it 'broadcasts the new keys for the specified account' do
|
||||
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_in)
|
||||
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_in).with(anything, account.id, anything).once
|
||||
end
|
||||
@@ -947,7 +989,8 @@ describe Mastodon::CLI::Accounts do
|
||||
old_private_keys = accounts.map(&:private_key)
|
||||
old_public_keys = accounts.map(&:public_key)
|
||||
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('rotated')
|
||||
accounts.each(&:reload)
|
||||
|
||||
expect(accounts.map(&:private_key)).to_not eq(old_private_keys)
|
||||
@@ -957,7 +1000,8 @@ describe Mastodon::CLI::Accounts do
|
||||
it 'broadcasts the new keys for each account' do
|
||||
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_in)
|
||||
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('rotated')
|
||||
|
||||
accounts.each do |account|
|
||||
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_in).with(anything, account.id, anything).once
|
||||
@@ -1036,7 +1080,8 @@ describe Mastodon::CLI::Accounts do
|
||||
end
|
||||
|
||||
it 'merges `from_account` into `to_account` and deletes `from_account`' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(to_account).to have_received(:merge_with!).with(from_account).once
|
||||
expect(from_account).to have_received(:destroy).once
|
||||
@@ -1059,7 +1104,8 @@ describe Mastodon::CLI::Accounts do
|
||||
end
|
||||
|
||||
it 'merges "from_account" into "to_account" and deletes from_account' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(to_account).to have_received(:merge_with!).with(from_account).once
|
||||
expect(from_account).to have_received(:destroy)
|
||||
@@ -1339,7 +1385,8 @@ describe Mastodon::CLI::Accounts do
|
||||
|
||||
shared_examples 'a successful migration' do
|
||||
it 'calls the MoveService for the last migration' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
last_migration = source_account.migrations.last
|
||||
|
||||
@@ -1449,7 +1496,8 @@ describe Mastodon::CLI::Accounts do
|
||||
end
|
||||
|
||||
it 'creates a migration for the specified account with the target account' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('migrated')
|
||||
|
||||
last_migration = source_account.migrations.last
|
||||
|
||||
|
||||
@@ -78,7 +78,8 @@ describe Mastodon::CLI::IpBlocks do
|
||||
|
||||
it 'overwrites the existing IP block record' do
|
||||
expect { subject }
|
||||
.to change { blocked_ip.reload.severity }
|
||||
.to output_results('Added 11')
|
||||
.and change { blocked_ip.reload.severity }
|
||||
.from('no_access')
|
||||
.to('sign_up_requires_approval')
|
||||
end
|
||||
@@ -189,7 +190,8 @@ describe Mastodon::CLI::IpBlocks do
|
||||
let(:options) { { force: true } }
|
||||
|
||||
it 'removes blocks for IP ranges that cover given IP(s) and keeps other ranges' do
|
||||
subject
|
||||
expect { subject }
|
||||
.to output_results('Removed 2')
|
||||
|
||||
expect(covered_ranges).to_not exist
|
||||
expect(other_ranges).to exist
|
||||
|
||||
@@ -41,7 +41,8 @@ describe Mastodon::CLI::Settings do
|
||||
|
||||
it 'changes registrations_mode and require_invite_text' do
|
||||
expect { subject }
|
||||
.to change(Setting, :registrations_mode).from(nil).to('approved')
|
||||
.to output_results('OK')
|
||||
.and change(Setting, :registrations_mode).from(nil).to('approved')
|
||||
.and change(Setting, :require_invite_text).from(false).to(true)
|
||||
end
|
||||
end
|
||||
|
||||
210
spec/models/announcement_spec.rb
Normal file
210
spec/models/announcement_spec.rb
Normal file
@@ -0,0 +1,210 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Announcement do
|
||||
describe 'Scopes' do
|
||||
context 'with published and unpublished records' do
|
||||
let!(:published) { Fabricate(:announcement, published: true) }
|
||||
let!(:unpublished) { Fabricate(:announcement, published: false, scheduled_at: 10.days.from_now) }
|
||||
|
||||
describe '#unpublished' do
|
||||
it 'returns records with published false' do
|
||||
results = described_class.unpublished
|
||||
|
||||
expect(results).to eq([unpublished])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#published' do
|
||||
it 'returns records with published true' do
|
||||
results = described_class.published
|
||||
|
||||
expect(results).to eq([published])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#without_muted' do
|
||||
let!(:announcement) { Fabricate(:announcement) }
|
||||
let(:account) { Fabricate(:account) }
|
||||
let(:muted_announcement) { Fabricate(:announcement) }
|
||||
|
||||
before do
|
||||
Fabricate(:announcement_mute, account: account, announcement: muted_announcement)
|
||||
end
|
||||
|
||||
it 'returns the announcements not muted by the account' do
|
||||
results = described_class.without_muted(account)
|
||||
expect(results).to include(announcement)
|
||||
expect(results).to_not include(muted_announcement)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with timestamped announcements' do
|
||||
let!(:adam_announcement) { Fabricate(:announcement, starts_at: 100.days.ago, scheduled_at: 10.days.ago, published_at: 10.days.ago, ends_at: 5.days.from_now) }
|
||||
let!(:brenda_announcement) { Fabricate(:announcement, starts_at: 10.days.ago, scheduled_at: 100.days.ago, published_at: 10.days.ago, ends_at: 5.days.from_now) }
|
||||
let!(:clara_announcement) { Fabricate(:announcement, starts_at: 10.days.ago, scheduled_at: 10.days.ago, published_at: 100.days.ago, ends_at: 5.days.from_now) }
|
||||
let!(:darnelle_announcement) { Fabricate(:announcement, starts_at: 10.days.ago, scheduled_at: 10.days.ago, published_at: 10.days.ago, ends_at: 5.days.from_now, created_at: 100.days.ago) }
|
||||
|
||||
describe '#chronological' do
|
||||
it 'orders the records correctly' do
|
||||
results = described_class.chronological
|
||||
|
||||
expect(results).to eq(
|
||||
[
|
||||
adam_announcement,
|
||||
brenda_announcement,
|
||||
clara_announcement,
|
||||
darnelle_announcement,
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#reverse_chronological' do
|
||||
it 'orders the records correctly' do
|
||||
results = described_class.reverse_chronological
|
||||
|
||||
expect(results).to eq(
|
||||
[
|
||||
darnelle_announcement,
|
||||
clara_announcement,
|
||||
brenda_announcement,
|
||||
adam_announcement,
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Validations' do
|
||||
describe 'text' do
|
||||
it 'validates presence of attribute' do
|
||||
record = Fabricate.build(:announcement, text: nil)
|
||||
|
||||
expect(record).to_not be_valid
|
||||
expect(record.errors[:text]).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
describe 'ends_at' do
|
||||
it 'validates presence when starts_at is present' do
|
||||
record = Fabricate.build(:announcement, starts_at: 1.day.ago)
|
||||
|
||||
expect(record).to_not be_valid
|
||||
expect(record.errors[:ends_at]).to be_present
|
||||
end
|
||||
|
||||
it 'does not validate presence when starts_at is missing' do
|
||||
record = Fabricate.build(:announcement, starts_at: nil)
|
||||
|
||||
expect(record).to be_valid
|
||||
expect(record.errors[:ends_at]).to_not be_present
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#publish!' do
|
||||
it 'publishes an unpublished record' do
|
||||
announcement = Fabricate(:announcement, published: false, scheduled_at: 10.days.from_now)
|
||||
|
||||
announcement.publish!
|
||||
|
||||
expect(announcement).to be_published
|
||||
expect(announcement.published_at).to_not be_nil
|
||||
expect(announcement.scheduled_at).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#unpublish!' do
|
||||
it 'unpublishes a published record' do
|
||||
announcement = Fabricate(:announcement, published: true)
|
||||
|
||||
announcement.unpublish!
|
||||
|
||||
expect(announcement).to_not be_published
|
||||
expect(announcement.scheduled_at).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#time_range?' do
|
||||
it 'returns false when starts_at and ends_at are missing' do
|
||||
record = Fabricate.build(:announcement, starts_at: nil, ends_at: nil)
|
||||
|
||||
expect(record.time_range?).to be(false)
|
||||
end
|
||||
|
||||
it 'returns false when starts_at is present and ends_at is missing' do
|
||||
record = Fabricate.build(:announcement, starts_at: 5.days.from_now, ends_at: nil)
|
||||
|
||||
expect(record.time_range?).to be(false)
|
||||
end
|
||||
|
||||
it 'returns false when starts_at is missing and ends_at is present' do
|
||||
record = Fabricate.build(:announcement, starts_at: nil, ends_at: 5.days.from_now)
|
||||
|
||||
expect(record.time_range?).to be(false)
|
||||
end
|
||||
|
||||
it 'returns true when starts_at and ends_at are present' do
|
||||
record = Fabricate.build(:announcement, starts_at: 5.days.from_now, ends_at: 10.days.from_now)
|
||||
|
||||
expect(record.time_range?).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#reactions' do
|
||||
context 'with announcement_reactions present' do
|
||||
let!(:account) { Fabricate(:account) }
|
||||
let!(:announcement) { Fabricate(:announcement) }
|
||||
let!(:announcement_reaction) { Fabricate(:announcement_reaction, announcement: announcement, created_at: 10.days.ago) }
|
||||
let!(:announcement_reaction_account) { Fabricate(:announcement_reaction, announcement: announcement, created_at: 5.days.ago, account: account) }
|
||||
|
||||
before do
|
||||
Fabricate(:announcement_reaction)
|
||||
end
|
||||
|
||||
it 'returns the announcement reactions for the announcement' do
|
||||
results = announcement.reactions
|
||||
|
||||
expect(results.first.name).to eq(announcement_reaction.name)
|
||||
expect(results.last.name).to eq(announcement_reaction_account.name)
|
||||
end
|
||||
|
||||
it 'returns the announcement reactions for the announcement limited to account' do
|
||||
results = announcement.reactions(account)
|
||||
|
||||
expect(results.first.name).to eq(announcement_reaction.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#statuses' do
|
||||
let(:announcement) { Fabricate(:announcement, status_ids: status_ids) }
|
||||
|
||||
context 'with empty status_ids' do
|
||||
let(:status_ids) { nil }
|
||||
|
||||
it 'returns empty array' do
|
||||
results = announcement.statuses
|
||||
|
||||
expect(results).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
context 'with relevant status_ids' do
|
||||
let(:status) { Fabricate(:status, visibility: :public) }
|
||||
let(:direct_status) { Fabricate(:status, visibility: :direct) }
|
||||
let(:status_ids) { [status.id, direct_status.id] }
|
||||
|
||||
it 'returns public and unlisted statuses' do
|
||||
results = announcement.statuses
|
||||
|
||||
expect(results).to include(status)
|
||||
expect(results).to_not include(direct_status)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -59,7 +59,7 @@ RSpec.describe CustomEmoji do
|
||||
describe '.from_text' do
|
||||
subject { described_class.from_text(text, nil) }
|
||||
|
||||
let!(:emojo) { Fabricate(:custom_emoji) }
|
||||
let!(:emojo) { Fabricate(:custom_emoji, shortcode: 'coolcat') }
|
||||
|
||||
context 'with plain text' do
|
||||
let(:text) { 'Hello :coolcat:' }
|
||||
|
||||
@@ -104,7 +104,6 @@ RSpec.configure do |config|
|
||||
end
|
||||
|
||||
config.before :each, type: :cli do
|
||||
stub_stdout
|
||||
stub_reset_connection_pools
|
||||
end
|
||||
|
||||
@@ -163,14 +162,6 @@ def attachment_fixture(name)
|
||||
Rails.root.join('spec', 'fixtures', 'files', name).open
|
||||
end
|
||||
|
||||
def stub_stdout
|
||||
# TODO: Is there a bettery way to:
|
||||
# - Avoid CLI command output being printed out
|
||||
# - Allow rspec to assert things against STDOUT
|
||||
# - Avoid disabling stdout for other desirable output (deprecation warnings, for example)
|
||||
allow($stdout).to receive(:write)
|
||||
end
|
||||
|
||||
def stub_reset_connection_pools
|
||||
# TODO: Is there a better way to correctly run specs without stubbing this?
|
||||
# (Avoids reset_connection_pools! in test env)
|
||||
|
||||
@@ -9,7 +9,7 @@ describe 'Custom Emojis' do
|
||||
|
||||
describe 'GET /api/v1/custom_emojis' do
|
||||
before do
|
||||
Fabricate(:custom_emoji, domain: nil, disabled: false, visible_in_picker: true)
|
||||
Fabricate(:custom_emoji, domain: nil, disabled: false, visible_in_picker: true, shortcode: 'coolcat')
|
||||
end
|
||||
|
||||
context 'when logged out' do
|
||||
|
||||
@@ -2,17 +2,13 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::DirectoriesController do
|
||||
render_views
|
||||
|
||||
describe 'Directories API' do
|
||||
let(:user) { Fabricate(:user, confirmed_at: nil) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:follows') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'read:follows' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
describe 'GET /api/v1/directories' do
|
||||
context 'with no params' do
|
||||
before do
|
||||
local_unconfirmed_account = Fabricate(
|
||||
@@ -58,27 +54,32 @@ describe Api::V1::DirectoriesController do
|
||||
)
|
||||
domain_blocked_account.create_account_stat!
|
||||
Fabricate(:account_domain_block, account: user.account, domain: 'test.example')
|
||||
|
||||
local_discoverable_account.create_account_stat!
|
||||
eligible_remote_account.create_account_stat!
|
||||
end
|
||||
|
||||
it 'returns the local discoverable account and the remote discoverable account' do
|
||||
local_discoverable_account = Fabricate(
|
||||
let(:local_discoverable_account) do
|
||||
Fabricate(
|
||||
:account,
|
||||
domain: nil,
|
||||
user: Fabricate(:user, confirmed_at: 10.days.ago, approved: true),
|
||||
discoverable: true,
|
||||
username: 'local_discoverable'
|
||||
)
|
||||
local_discoverable_account.create_account_stat!
|
||||
end
|
||||
|
||||
eligible_remote_account = Fabricate(
|
||||
let(:eligible_remote_account) do
|
||||
Fabricate(
|
||||
:account,
|
||||
domain: 'host.example',
|
||||
discoverable: true,
|
||||
username: 'eligible_remote'
|
||||
)
|
||||
eligible_remote_account.create_account_stat!
|
||||
end
|
||||
|
||||
get :show
|
||||
it 'returns the local discoverable account and the remote discoverable account' do
|
||||
get '/api/v1/directory', headers: headers
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json.size).to eq(2)
|
||||
@@ -87,14 +88,17 @@ describe Api::V1::DirectoriesController do
|
||||
end
|
||||
|
||||
context 'when asking for local accounts only' do
|
||||
it 'returns only the local accounts' do
|
||||
user = Fabricate(:user, confirmed_at: 10.days.ago, approved: true)
|
||||
local_account = Fabricate(:account, domain: nil, user: user)
|
||||
remote_account = Fabricate(:account, domain: 'host.example')
|
||||
let(:user) { Fabricate(:user, confirmed_at: 10.days.ago, approved: true) }
|
||||
let(:local_account) { Fabricate(:account, domain: nil, user: user) }
|
||||
let(:remote_account) { Fabricate(:account, domain: 'host.example') }
|
||||
|
||||
before do
|
||||
local_account.create_account_stat!
|
||||
remote_account.create_account_stat!
|
||||
end
|
||||
|
||||
get :show, params: { local: '1' }
|
||||
it 'returns only the local accounts' do
|
||||
get '/api/v1/directory', headers: headers, params: { local: '1' }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json.size).to eq(1)
|
||||
@@ -108,7 +112,7 @@ describe Api::V1::DirectoriesController do
|
||||
old_stat = Fabricate(:account_stat, last_status_at: 1.day.ago)
|
||||
new_stat = Fabricate(:account_stat, last_status_at: 1.minute.ago)
|
||||
|
||||
get :show, params: { order: 'active' }
|
||||
get '/api/v1/directory', headers: headers, params: { order: 'active' }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json.size).to eq(2)
|
||||
@@ -123,7 +127,7 @@ describe Api::V1::DirectoriesController do
|
||||
travel_to 10.seconds.from_now
|
||||
account_new = Fabricate(:account_stat).account
|
||||
|
||||
get :show, params: { order: 'new' }
|
||||
get '/api/v1/directory', headers: headers, params: { order: 'new' }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json.size).to eq(2)
|
||||
@@ -50,11 +50,11 @@ RSpec.describe DeleteAccountService, type: :service do
|
||||
end
|
||||
|
||||
def delete_associated_target_records
|
||||
change do
|
||||
[
|
||||
AccountPin.where(target_account: account),
|
||||
].map(&:count)
|
||||
end.from([1]).to([0])
|
||||
change(account_pins_for_account, :count).from(1).to(0)
|
||||
end
|
||||
|
||||
def account_pins_for_account
|
||||
AccountPin.where(target_account: account)
|
||||
end
|
||||
|
||||
def delete_associated_target_notifications
|
||||
@@ -100,28 +100,34 @@ RSpec.describe DeleteAccountService, type: :service do
|
||||
it 'sends expected activities to followed and follower inboxes' do
|
||||
subject
|
||||
|
||||
expect(a_request(:post, account.inbox_url).with(
|
||||
body:
|
||||
hash_including({
|
||||
'type' => 'Reject',
|
||||
'object' => hash_including({
|
||||
'type' => 'Follow',
|
||||
'actor' => account.uri,
|
||||
'object' => ActivityPub::TagManager.instance.uri_for(local_follower),
|
||||
}),
|
||||
})
|
||||
)).to have_been_made.once
|
||||
expect(post_to_inbox_with_reject).to have_been_made.once
|
||||
expect(post_to_inbox_with_undo).to have_been_made.once
|
||||
end
|
||||
|
||||
expect(a_request(:post, account.inbox_url).with(
|
||||
body: hash_including({
|
||||
'type' => 'Undo',
|
||||
'object' => hash_including({
|
||||
'type' => 'Follow',
|
||||
'actor' => ActivityPub::TagManager.instance.uri_for(local_follower),
|
||||
'object' => account.uri,
|
||||
}),
|
||||
})
|
||||
)).to have_been_made.once
|
||||
def post_to_inbox_with_undo
|
||||
a_request(:post, account.inbox_url).with(
|
||||
body: hash_including({
|
||||
'type' => 'Undo',
|
||||
'object' => hash_including({
|
||||
'type' => 'Follow',
|
||||
'actor' => ActivityPub::TagManager.instance.uri_for(local_follower),
|
||||
'object' => account.uri,
|
||||
}),
|
||||
})
|
||||
)
|
||||
end
|
||||
|
||||
def post_to_inbox_with_reject
|
||||
a_request(:post, account.inbox_url).with(
|
||||
body: hash_including({
|
||||
'type' => 'Reject',
|
||||
'object' => hash_including({
|
||||
'type' => 'Follow',
|
||||
'actor' => account.uri,
|
||||
'object' => ActivityPub::TagManager.instance.uri_for(local_follower),
|
||||
}),
|
||||
})
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user