Merge pull request #159 from kmycode/upstream-20231021
Upstream 20231021
This commit is contained in:
commit
551a9e8216
133 changed files with 1159 additions and 817 deletions
|
@ -18,10 +18,14 @@ RSpec.describe Admin::Disputes::AppealsController do
|
|||
describe 'GET #index' do
|
||||
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
|
||||
|
||||
it 'lists appeals' do
|
||||
before { appeal }
|
||||
|
||||
it 'returns a page that lists details of appeals' do
|
||||
get :index
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.body).to include("<span class=\"username\">#{strike.account.username}</span>")
|
||||
expect(response.body).to include("<span class=\"target\">#{appeal.account.username}</span>")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ describe AccountControllerConcern do
|
|||
end
|
||||
|
||||
it 'sets link headers' do
|
||||
account = Fabricate(:account, username: 'username')
|
||||
Fabricate(:account, username: 'username')
|
||||
get 'success', params: { account_username: 'username' }
|
||||
expect(response.headers['Link'].to_s).to eq '<http://test.host/.well-known/webfinger?resource=acct%3Ausername%40cb6e6126.ngrok.io>; rel="lrdd"; type="application/jrd+json", <https://cb6e6126.ngrok.io/users/username>; rel="alternate"; type="application/activity+json"'
|
||||
end
|
||||
|
|
21
spec/helpers/admin/disputes_helper_spec.rb
Normal file
21
spec/helpers/admin/disputes_helper_spec.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::DisputesHelper do
|
||||
describe 'strike_action_label' do
|
||||
it 'returns html describing the appeal' do
|
||||
adam = Account.new(username: 'Adam')
|
||||
becky = Account.new(username: 'Becky')
|
||||
strike = AccountWarning.new(account: adam, action: :suspend)
|
||||
appeal = Appeal.new(strike: strike, account: becky)
|
||||
|
||||
expected = <<~OUTPUT.strip
|
||||
<span class="username">Adam</span> suspended <span class="target">Becky</span>'s account
|
||||
OUTPUT
|
||||
result = helper.strike_action_label(appeal)
|
||||
|
||||
expect(result).to eq(expected)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -179,14 +179,14 @@ describe JsonLdHelper do
|
|||
it 'deems a safe compacting as such' do
|
||||
json['object'].delete('convo')
|
||||
compacted = compact(json)
|
||||
deemed_compatible = patch_for_forwarding!(json, compacted)
|
||||
patch_for_forwarding!(json, compacted)
|
||||
expect(compacted['to']).to eq ['https://www.w3.org/ns/activitystreams#Public']
|
||||
expect(safe_for_forwarding?(json, compacted)).to be true
|
||||
end
|
||||
|
||||
it 'deems an unsafe compacting as such' do
|
||||
compacted = compact(json)
|
||||
deemed_compatible = patch_for_forwarding!(json, compacted)
|
||||
patch_for_forwarding!(json, compacted)
|
||||
expect(compacted['to']).to eq ['https://www.w3.org/ns/activitystreams#Public']
|
||||
expect(safe_for_forwarding?(json, compacted)).to be false
|
||||
end
|
||||
|
|
|
@ -34,6 +34,40 @@ RSpec.describe ActivityPub::LinkedDataSignature do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when local account record is missing a public key' do
|
||||
let(:raw_signature) do
|
||||
{
|
||||
'creator' => 'http://example.com/alice',
|
||||
'created' => '2017-09-23T20:21:34Z',
|
||||
}
|
||||
end
|
||||
|
||||
let(:signature) { raw_signature.merge('type' => 'RsaSignature2017', 'signatureValue' => sign(sender, raw_signature, raw_json)) }
|
||||
|
||||
let(:service_stub) { instance_double(ActivityPub::FetchRemoteKeyService) }
|
||||
|
||||
before do
|
||||
# Ensure signature is computed with the old key
|
||||
signature
|
||||
|
||||
# Unset key
|
||||
old_key = sender.public_key
|
||||
sender.update!(private_key: '', public_key: '')
|
||||
|
||||
allow(ActivityPub::FetchRemoteKeyService).to receive(:new).and_return(service_stub)
|
||||
|
||||
allow(service_stub).to receive(:call).with('http://example.com/alice', id: false) do
|
||||
sender.update!(public_key: old_key)
|
||||
sender
|
||||
end
|
||||
end
|
||||
|
||||
it 'fetches key and returns creator' do
|
||||
expect(subject.verify_actor!).to eq sender
|
||||
expect(service_stub).to have_received(:call).with('http://example.com/alice', id: false).once
|
||||
end
|
||||
end
|
||||
|
||||
context 'when signature is missing' do
|
||||
let(:signature) { nil }
|
||||
|
||||
|
|
|
@ -1356,4 +1356,254 @@ describe Mastodon::CLI::Accounts do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#prune' do
|
||||
let!(:local_account) { Fabricate(:account) }
|
||||
let!(:bot_account) { Fabricate(:account, bot: true, domain: 'example.com') }
|
||||
let!(:group_account) { Fabricate(:account, actor_type: 'Group', domain: 'example.com') }
|
||||
let!(:mentioned_account) { Fabricate(:account, domain: 'example.com') }
|
||||
let!(:prunable_accounts) do
|
||||
Fabricate.times(3, :account, domain: 'example.com', bot: false, suspended_at: nil, silenced_at: nil)
|
||||
end
|
||||
|
||||
before do
|
||||
Fabricate(:mention, account: mentioned_account, status: Fabricate(:status, account: Fabricate(:account)))
|
||||
stub_parallelize_with_progress!
|
||||
end
|
||||
|
||||
it 'prunes all remote accounts with no interactions with local users' do
|
||||
cli.prune
|
||||
|
||||
prunable_account_ids = prunable_accounts.pluck(:id)
|
||||
|
||||
expect(Account.where(id: prunable_account_ids).count).to eq(0)
|
||||
end
|
||||
|
||||
it 'displays a successful message' do
|
||||
expect { cli.prune }.to output(
|
||||
a_string_including("OK, pruned #{prunable_accounts.size} accounts")
|
||||
).to_stdout
|
||||
end
|
||||
|
||||
it 'does not prune local accounts' do
|
||||
cli.prune
|
||||
|
||||
expect(Account.exists?(id: local_account.id)).to be(true)
|
||||
end
|
||||
|
||||
it 'does not prune bot accounts' do
|
||||
cli.prune
|
||||
|
||||
expect(Account.exists?(id: bot_account.id)).to be(true)
|
||||
end
|
||||
|
||||
it 'does not prune group accounts' do
|
||||
cli.prune
|
||||
|
||||
expect(Account.exists?(id: group_account.id)).to be(true)
|
||||
end
|
||||
|
||||
it 'does not prune accounts that have been mentioned' do
|
||||
cli.prune
|
||||
|
||||
expect(Account.exists?(id: mentioned_account.id)).to be true
|
||||
end
|
||||
|
||||
context 'with --dry-run option' do
|
||||
before do
|
||||
cli.options = { dry_run: true }
|
||||
end
|
||||
|
||||
it 'does not prune any account' do
|
||||
cli.prune
|
||||
|
||||
prunable_account_ids = prunable_accounts.pluck(:id)
|
||||
|
||||
expect(Account.where(id: prunable_account_ids).count).to eq(prunable_accounts.size)
|
||||
end
|
||||
|
||||
it 'displays a successful message with (DRY RUN)' do
|
||||
expect { cli.prune }.to output(
|
||||
a_string_including("OK, pruned #{prunable_accounts.size} accounts (DRY RUN)")
|
||||
).to_stdout
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#migrate' do
|
||||
let!(:source_account) { Fabricate(:account) }
|
||||
let!(:target_account) { Fabricate(:account, domain: 'example.com') }
|
||||
let(:arguments) { [source_account.username] }
|
||||
let(:resolve_account_service) { instance_double(ResolveAccountService, call: nil) }
|
||||
let(:move_service) { instance_double(MoveService, call: nil) }
|
||||
|
||||
before do
|
||||
allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service)
|
||||
allow(MoveService).to receive(:new).and_return(move_service)
|
||||
end
|
||||
|
||||
shared_examples 'a successful migration' do
|
||||
it 'calls the MoveService for the last migration' do
|
||||
cli.invoke(:migrate, arguments, options)
|
||||
|
||||
last_migration = source_account.migrations.last
|
||||
|
||||
expect(move_service).to have_received(:call).with(last_migration).once
|
||||
end
|
||||
|
||||
it 'displays a successful message' do
|
||||
expect { cli.invoke(:migrate, arguments, options) }.to output(
|
||||
a_string_including("OK, migrated #{source_account.acct} to #{target_account.acct}")
|
||||
).to_stdout
|
||||
end
|
||||
end
|
||||
|
||||
context 'when both --replay and --target options are given' do
|
||||
let(:options) { { replay: true, target: "#{target_account.username}@example.com" } }
|
||||
|
||||
it 'exits with an error message indicating that using both options is not possible' do
|
||||
expect { cli.invoke(:migrate, arguments, options) }.to output(
|
||||
a_string_including('Use --replay or --target, not both')
|
||||
).to_stdout
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no option is given' do
|
||||
it 'exits with an error message indicating that at least one option must be used' do
|
||||
expect { cli.invoke(:migrate, arguments, {}) }.to output(
|
||||
a_string_including('Use either --replay or --target')
|
||||
).to_stdout
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the given username is not found' do
|
||||
let(:arguments) { ['non_existent_username'] }
|
||||
|
||||
it 'exits with an error message indicating that there is no such account' do
|
||||
expect { cli.invoke(:migrate, arguments, replay: true) }.to output(
|
||||
a_string_including("No such account: #{arguments.first}")
|
||||
).to_stdout
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with --replay option' do
|
||||
let(:options) { { replay: true } }
|
||||
|
||||
context 'when the specified account has no previous migrations' do
|
||||
it 'exits with an error message indicating that the given account has no previous migrations' do
|
||||
expect { cli.invoke(:migrate, arguments, options) }.to output(
|
||||
a_string_including('The specified account has not performed any migration')
|
||||
).to_stdout
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the specified account has a previous migration' do
|
||||
before do
|
||||
allow(resolve_account_service).to receive(:call).with(source_account.acct, any_args).and_return(source_account)
|
||||
allow(resolve_account_service).to receive(:call).with(target_account.acct, any_args).and_return(target_account)
|
||||
target_account.aliases.create!(acct: source_account.acct)
|
||||
source_account.migrations.create!(acct: target_account.acct)
|
||||
source_account.update!(moved_to_account: target_account)
|
||||
end
|
||||
|
||||
it_behaves_like 'a successful migration'
|
||||
|
||||
context 'when the specified account is redirecting to a different target account' do
|
||||
before do
|
||||
source_account.update!(moved_to_account: nil)
|
||||
end
|
||||
|
||||
it 'exits with an error message' do
|
||||
expect { cli.invoke(:migrate, arguments, options) }.to output(
|
||||
a_string_including('The specified account is not redirecting to its last migration target. Use --force if you want to replay the migration anyway')
|
||||
).to_stdout
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with --force option' do
|
||||
let(:options) { { replay: true, force: true } }
|
||||
|
||||
it_behaves_like 'a successful migration'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with --target option' do
|
||||
let(:options) { { target: target_account.acct } }
|
||||
|
||||
before do
|
||||
allow(resolve_account_service).to receive(:call).with(source_account.acct, any_args).and_return(source_account)
|
||||
allow(resolve_account_service).to receive(:call).with(target_account.acct, any_args).and_return(target_account)
|
||||
end
|
||||
|
||||
context 'when the specified target account is not found' do
|
||||
before do
|
||||
allow(resolve_account_service).to receive(:call).with(target_account.acct).and_return(nil)
|
||||
end
|
||||
|
||||
it 'exits with an error message indicating that there is no such account' do
|
||||
expect { cli.invoke(:migrate, arguments, options) }.to output(
|
||||
a_string_including("The specified target account could not be found: #{options[:target]}")
|
||||
).to_stdout
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the specified target account exists' do
|
||||
before do
|
||||
target_account.aliases.create!(acct: source_account.acct)
|
||||
end
|
||||
|
||||
it 'creates a migration for the specified account with the target account' do
|
||||
cli.invoke(:migrate, arguments, options)
|
||||
|
||||
last_migration = source_account.migrations.last
|
||||
|
||||
expect(last_migration.acct).to eq(target_account.acct)
|
||||
end
|
||||
|
||||
it_behaves_like 'a successful migration'
|
||||
end
|
||||
|
||||
context 'when the migration record is invalid' do
|
||||
it 'exits with an error indicating that the validation failed' do
|
||||
expect { cli.invoke(:migrate, arguments, options) }.to output(
|
||||
a_string_including('Error: Validation failed')
|
||||
).to_stdout
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the specified account is redirecting to a different target account' do
|
||||
before do
|
||||
allow(Account).to receive(:find_local).with(source_account.username).and_return(source_account)
|
||||
allow(source_account).to receive(:moved_to_account_id).and_return(-1)
|
||||
end
|
||||
|
||||
it 'exits with an error message' do
|
||||
expect { cli.invoke(:migrate, arguments, options) }.to output(
|
||||
a_string_including('The specified account is redirecting to a different target account. Use --force if you want to change the migration target')
|
||||
).to_stdout
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with --target and --force options' do
|
||||
let(:options) { { target: target_account.acct, force: true } }
|
||||
|
||||
before do
|
||||
target_account.aliases.create!(acct: source_account.acct)
|
||||
allow(Account).to receive(:find_local).with(source_account.username).and_return(source_account)
|
||||
allow(source_account).to receive(:moved_to_account_id).and_return(-1)
|
||||
end
|
||||
|
||||
it_behaves_like 'a successful migration'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -557,7 +557,7 @@ RSpec.describe Account do
|
|||
end
|
||||
|
||||
it 'does not return suspended users' do
|
||||
match = Fabricate(
|
||||
Fabricate(
|
||||
:account,
|
||||
display_name: 'Display Name',
|
||||
username: 'username',
|
||||
|
@ -684,7 +684,7 @@ RSpec.describe Account do
|
|||
end
|
||||
|
||||
it 'does not return non-followed accounts' do
|
||||
match = Fabricate(
|
||||
Fabricate(
|
||||
:account,
|
||||
display_name: 'A & l & i & c & e',
|
||||
username: 'username',
|
||||
|
@ -696,7 +696,7 @@ RSpec.describe Account do
|
|||
end
|
||||
|
||||
it 'does not return suspended users' do
|
||||
match = Fabricate(
|
||||
Fabricate(
|
||||
:account,
|
||||
display_name: 'Display Name',
|
||||
username: 'username',
|
||||
|
@ -736,7 +736,7 @@ RSpec.describe Account do
|
|||
end
|
||||
|
||||
it 'does not return suspended users' do
|
||||
match = Fabricate(
|
||||
Fabricate(
|
||||
:account,
|
||||
display_name: 'Display Name',
|
||||
username: 'username',
|
||||
|
@ -920,10 +920,10 @@ RSpec.describe Account do
|
|||
|
||||
context 'when is local' do
|
||||
it 'is invalid if the username is not unique in case-insensitive comparison among local accounts' do
|
||||
account_1 = Fabricate(:account, username: 'the_doctor')
|
||||
account_2 = Fabricate.build(:account, username: 'the_Doctor')
|
||||
account_2.valid?
|
||||
expect(account_2).to model_have_error_on_field(:username)
|
||||
_account = Fabricate(:account, username: 'the_doctor')
|
||||
non_unique_account = Fabricate.build(:account, username: 'the_Doctor')
|
||||
non_unique_account.valid?
|
||||
expect(non_unique_account).to model_have_error_on_field(:username)
|
||||
end
|
||||
|
||||
it 'is invalid if the username is reserved' do
|
||||
|
@ -944,9 +944,9 @@ RSpec.describe Account do
|
|||
end
|
||||
|
||||
it 'is valid if we are creating a possibly-conflicting instance actor account' do
|
||||
account_1 = Fabricate(:account, username: 'examplecom')
|
||||
account_2 = Fabricate.build(:account, id: -99, actor_type: 'Application', locked: true, username: 'example.com')
|
||||
expect(account_2.valid?).to be true
|
||||
_account = Fabricate(:account, username: 'examplecom')
|
||||
instance_account = Fabricate.build(:account, id: -99, actor_type: 'Application', locked: true, username: 'example.com')
|
||||
expect(instance_account.valid?).to be true
|
||||
end
|
||||
|
||||
it 'is invalid if the username doesn\'t only contains letters, numbers and underscores' do
|
||||
|
@ -1078,17 +1078,17 @@ RSpec.describe Account do
|
|||
|
||||
describe 'remote' do
|
||||
it 'returns an array of accounts who have a domain' do
|
||||
account_1 = Fabricate(:account, domain: nil)
|
||||
account_2 = Fabricate(:account, domain: 'example.com')
|
||||
expect(described_class.remote).to contain_exactly(account_2)
|
||||
_account = Fabricate(:account, domain: nil)
|
||||
account_with_domain = Fabricate(:account, domain: 'example.com')
|
||||
expect(described_class.remote).to contain_exactly(account_with_domain)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'local' do
|
||||
it 'returns an array of accounts who do not have a domain' do
|
||||
account_1 = Fabricate(:account, domain: nil)
|
||||
account_2 = Fabricate(:account, domain: 'example.com')
|
||||
expect(described_class.where('id > 0').local).to contain_exactly(account_1)
|
||||
local_account = Fabricate(:account, domain: nil)
|
||||
_account_with_domain = Fabricate(:account, domain: 'example.com')
|
||||
expect(described_class.where('id > 0').local).to contain_exactly(local_account)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1112,17 +1112,17 @@ RSpec.describe Account do
|
|||
|
||||
describe 'silenced' do
|
||||
it 'returns an array of accounts who are silenced' do
|
||||
account_1 = Fabricate(:account, silenced: true)
|
||||
account_2 = Fabricate(:account, silenced: false)
|
||||
expect(described_class.silenced).to contain_exactly(account_1)
|
||||
silenced_account = Fabricate(:account, silenced: true)
|
||||
_account = Fabricate(:account, silenced: false)
|
||||
expect(described_class.silenced).to contain_exactly(silenced_account)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'suspended' do
|
||||
it 'returns an array of accounts who are suspended' do
|
||||
account_1 = Fabricate(:account, suspended: true)
|
||||
account_2 = Fabricate(:account, suspended: false)
|
||||
expect(described_class.suspended).to contain_exactly(account_1)
|
||||
suspended_account = Fabricate(:account, suspended: true)
|
||||
_account = Fabricate(:account, suspended: false)
|
||||
expect(described_class.suspended).to contain_exactly(suspended_account)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -11,10 +11,10 @@ RSpec.describe DomainBlock do
|
|||
end
|
||||
|
||||
it 'is invalid if the same normalized domain already exists' do
|
||||
domain_block_1 = Fabricate(:domain_block, domain: 'にゃん')
|
||||
domain_block_2 = Fabricate.build(:domain_block, domain: 'xn--r9j5b5b')
|
||||
domain_block_2.valid?
|
||||
expect(domain_block_2).to model_have_error_on_field(:domain)
|
||||
_domain_block = Fabricate(:domain_block, domain: 'にゃん')
|
||||
domain_block_with_normalized_value = Fabricate.build(:domain_block, domain: 'xn--r9j5b5b')
|
||||
domain_block_with_normalized_value.valid?
|
||||
expect(domain_block_with_normalized_value).to model_have_error_on_field(:domain)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
28
spec/models/preview_card_spec.rb
Normal file
28
spec/models/preview_card_spec.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe PreviewCard do
|
||||
describe 'validations' do
|
||||
describe 'urls' do
|
||||
it 'allows http schemes' do
|
||||
record = described_class.new(url: 'http://example.host/path')
|
||||
|
||||
expect(record).to be_valid
|
||||
end
|
||||
|
||||
it 'allows https schemes' do
|
||||
record = described_class.new(url: 'https://example.host/path')
|
||||
|
||||
expect(record).to be_valid
|
||||
end
|
||||
|
||||
it 'does not allow javascript: schemes' do
|
||||
record = described_class.new(url: 'javascript:alert()')
|
||||
|
||||
expect(record).to_not be_valid
|
||||
expect(record).to model_have_error_on_field(:url)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -341,7 +341,7 @@ RSpec.describe Status do
|
|||
|
||||
describe '#replies_count' do
|
||||
it 'is the number of replies' do
|
||||
reply = Fabricate(:status, account: bob, thread: subject)
|
||||
Fabricate(:status, account: bob, thread: subject)
|
||||
expect(subject.replies_count).to eq 1
|
||||
end
|
||||
|
||||
|
|
|
@ -55,17 +55,17 @@ RSpec.describe User do
|
|||
describe 'scopes' do
|
||||
describe 'recent' do
|
||||
it 'returns an array of recent users ordered by id' do
|
||||
user_1 = Fabricate(:user)
|
||||
user_2 = Fabricate(:user)
|
||||
expect(described_class.recent).to eq [user_2, user_1]
|
||||
first_user = Fabricate(:user)
|
||||
second_user = Fabricate(:user)
|
||||
expect(described_class.recent).to eq [second_user, first_user]
|
||||
end
|
||||
end
|
||||
|
||||
describe 'confirmed' do
|
||||
it 'returns an array of users who are confirmed' do
|
||||
user_1 = Fabricate(:user, confirmed_at: nil)
|
||||
user_2 = Fabricate(:user, confirmed_at: Time.zone.now)
|
||||
expect(described_class.confirmed).to contain_exactly(user_2)
|
||||
Fabricate(:user, confirmed_at: nil)
|
||||
confirmed_user = Fabricate(:user, confirmed_at: Time.zone.now)
|
||||
expect(described_class.confirmed).to contain_exactly(confirmed_user)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ RSpec.describe WebauthnCredential do
|
|||
end
|
||||
|
||||
it 'is invalid if already exist a webauthn credential with the same external id' do
|
||||
existing_webauthn_credential = Fabricate(:webauthn_credential, external_id: '_Typ0ygudDnk9YUVWLQayw')
|
||||
Fabricate(:webauthn_credential, external_id: '_Typ0ygudDnk9YUVWLQayw')
|
||||
new_webauthn_credential = Fabricate.build(:webauthn_credential, external_id: '_Typ0ygudDnk9YUVWLQayw')
|
||||
|
||||
new_webauthn_credential.valid?
|
||||
|
@ -47,7 +47,7 @@ RSpec.describe WebauthnCredential do
|
|||
|
||||
it 'is invalid if user already registered a webauthn credential with the same nickname' do
|
||||
user = Fabricate(:user)
|
||||
existing_webauthn_credential = Fabricate(:webauthn_credential, user_id: user.id, nickname: 'USB Key')
|
||||
Fabricate(:webauthn_credential, user_id: user.id, nickname: 'USB Key')
|
||||
new_webauthn_credential = Fabricate.build(:webauthn_credential, user_id: user.id, nickname: 'USB Key')
|
||||
|
||||
new_webauthn_credential.valid?
|
||||
|
|
|
@ -9,7 +9,8 @@ describe 'Credentials' do
|
|||
end
|
||||
|
||||
context 'with an oauth token' do
|
||||
let(:token) { Fabricate(:accessible_access_token, scopes: 'read', application: Fabricate(:application)) }
|
||||
let(:application) { Fabricate(:application, scopes: 'read') }
|
||||
let(:token) { Fabricate(:accessible_access_token, application: application) }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
|
||||
it 'returns the app information correctly', :aggregate_failures do
|
||||
|
@ -21,7 +22,35 @@ describe 'Credentials' do
|
|||
a_hash_including(
|
||||
name: token.application.name,
|
||||
website: token.application.website,
|
||||
vapid_key: Rails.configuration.x.vapid_public_key
|
||||
vapid_key: Rails.configuration.x.vapid_public_key,
|
||||
scopes: token.application.scopes.map(&:to_s),
|
||||
client_id: token.application.uid
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a non-read scoped oauth token' do
|
||||
let(:application) { Fabricate(:application, scopes: 'admin:write') }
|
||||
let(:token) { Fabricate(:accessible_access_token, application: application) }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns the app information correctly' do
|
||||
subject
|
||||
|
||||
expect(body_as_json).to match(
|
||||
a_hash_including(
|
||||
name: token.application.name,
|
||||
website: token.application.website,
|
||||
vapid_key: Rails.configuration.x.vapid_public_key,
|
||||
scopes: token.application.scopes.map(&:to_s),
|
||||
client_id: token.application.uid
|
||||
)
|
||||
)
|
||||
end
|
||||
|
@ -36,5 +65,49 @@ describe 'Credentials' do
|
|||
expect(response).to have_http_status(401)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a revoked oauth token' do
|
||||
let(:application) { Fabricate(:application, scopes: 'read') }
|
||||
let(:token) { Fabricate(:accessible_access_token, application: application, revoked_at: DateTime.now.utc) }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
|
||||
it 'returns http authorization error' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(401)
|
||||
end
|
||||
|
||||
it 'returns the error in the json response' do
|
||||
subject
|
||||
|
||||
expect(body_as_json).to match(
|
||||
a_hash_including(
|
||||
error: 'The access token was revoked'
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an invalid oauth token' do
|
||||
let(:application) { Fabricate(:application, scopes: 'read') }
|
||||
let(:token) { Fabricate(:accessible_access_token, application: application) }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}-invalid" } }
|
||||
|
||||
it 'returns http authorization error' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(401)
|
||||
end
|
||||
|
||||
it 'returns the error in the json response' do
|
||||
subject
|
||||
|
||||
expect(body_as_json).to match(
|
||||
a_hash_including(
|
||||
error: 'The access token is invalid'
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -56,7 +56,7 @@ describe AccountSearchService, type: :service do
|
|||
service = instance_double(ResolveAccountService, call: nil)
|
||||
allow(ResolveAccountService).to receive(:new).and_return(service)
|
||||
|
||||
results = subject.call('newuser@remote.com', nil, limit: 10, resolve: true)
|
||||
subject.call('newuser@remote.com', nil, limit: 10, resolve: true)
|
||||
expect(service).to have_received(:call).with('newuser@remote.com')
|
||||
end
|
||||
|
||||
|
@ -64,14 +64,14 @@ describe AccountSearchService, type: :service do
|
|||
service = instance_double(ResolveAccountService, call: nil)
|
||||
allow(ResolveAccountService).to receive(:new).and_return(service)
|
||||
|
||||
results = subject.call('newuser@remote.com', nil, limit: 10, resolve: false)
|
||||
subject.call('newuser@remote.com', nil, limit: 10, resolve: false)
|
||||
expect(service).to_not have_received(:call)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the fuzzy match first, and does not return suspended exacts' do
|
||||
partial = Fabricate(:account, username: 'exactness')
|
||||
exact = Fabricate(:account, username: 'exact', suspended: true)
|
||||
Fabricate(:account, username: 'exact', suspended: true)
|
||||
results = subject.call('exact', nil, limit: 10)
|
||||
|
||||
expect(results.size).to eq 1
|
||||
|
@ -79,7 +79,7 @@ describe AccountSearchService, type: :service do
|
|||
end
|
||||
|
||||
it 'does not return suspended remote accounts' do
|
||||
remote = Fabricate(:account, username: 'a', domain: 'remote', display_name: 'e', suspended: true)
|
||||
Fabricate(:account, username: 'a', domain: 'remote', display_name: 'e', suspended: true)
|
||||
results = subject.call('a@example.com', nil, limit: 2)
|
||||
|
||||
expect(results.size).to eq 0
|
||||
|
|
|
@ -307,7 +307,7 @@ RSpec.describe PostStatusService, type: :service do
|
|||
|
||||
it 'processes duplicate mentions correctly' do
|
||||
account = Fabricate(:account)
|
||||
mentioned_account = Fabricate(:account, username: 'alice')
|
||||
Fabricate(:account, username: 'alice')
|
||||
|
||||
expect do
|
||||
subject.call(account, text: '@alice @alice @alice hey @alice')
|
||||
|
@ -377,7 +377,7 @@ RSpec.describe PostStatusService, type: :service do
|
|||
account = Fabricate(:account)
|
||||
media = Fabricate(:media_attachment, account: Fabricate(:account))
|
||||
|
||||
status = subject.call(
|
||||
subject.call(
|
||||
account,
|
||||
text: 'test status update',
|
||||
media_ids: [media.id]
|
||||
|
@ -458,7 +458,7 @@ RSpec.describe PostStatusService, type: :service do
|
|||
|
||||
it 'hit ng words for mention' do
|
||||
account = Fabricate(:account)
|
||||
mentioned = Fabricate(:account, username: 'ohagi', domain: nil)
|
||||
Fabricate(:account, username: 'ohagi', domain: nil)
|
||||
text = 'ng word test @ohagi'
|
||||
Form::AdminSettings.new(ng_words_for_stranger_mention: 'test', stranger_mention_from_local_ng: '1').save
|
||||
|
||||
|
@ -467,7 +467,7 @@ RSpec.describe PostStatusService, type: :service do
|
|||
|
||||
it 'hit ng words for mention but local posts are not checked' do
|
||||
account = Fabricate(:account)
|
||||
mentioned = Fabricate(:account, username: 'ohagi', domain: nil)
|
||||
Fabricate(:account, username: 'ohagi', domain: nil)
|
||||
text = 'ng word test @ohagi'
|
||||
Form::AdminSettings.new(ng_words_for_stranger_mention: 'test', stranger_mention_from_local_ng: '0').save
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ RSpec.describe PrecomputeFeedService, type: :service do
|
|||
muted_account = Fabricate(:account)
|
||||
Fabricate(:mute, account: account, target_account: muted_account)
|
||||
reblog = Fabricate(:status, account: muted_account)
|
||||
status = Fabricate(:status, account: account, reblog: reblog)
|
||||
Fabricate(:status, account: account, reblog: reblog)
|
||||
|
||||
subject.call(account)
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ describe ResolveURLService, type: :service do
|
|||
|
||||
describe '#call' do
|
||||
it 'returns nil when there is no resource url' do
|
||||
url = 'http://example.com/missing-resource'
|
||||
known_account = Fabricate(:account, uri: url, domain: 'example.com')
|
||||
url = 'http://example.com/missing-resource'
|
||||
Fabricate(:account, uri: url, domain: 'example.com')
|
||||
service = instance_double(FetchResourceService)
|
||||
|
||||
allow(FetchResourceService).to receive(:new).and_return service
|
||||
|
|
|
@ -44,7 +44,7 @@ RSpec.configure do |config|
|
|||
config.display_try_failure_messages = true
|
||||
|
||||
# Use the GitHub Annotations formatter for CI
|
||||
if ENV['GITHUB_ACTIONS'] == 'true'
|
||||
if ENV['GITHUB_ACTIONS'] == 'true' && ENV['GITHUB_RSPEC'] == 'true'
|
||||
require 'rspec/github'
|
||||
config.add_formatter RSpec::Github::Formatter
|
||||
end
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'admin/trends/links/_preview_card.html.haml' do
|
||||
it 'correctly escapes user supplied url values' do
|
||||
form = instance_double(ActionView::Helpers::FormHelper, check_box: nil)
|
||||
trend = PreviewCardTrend.new(allowed: false)
|
||||
preview_card = Fabricate.build(
|
||||
:preview_card,
|
||||
url: 'https://host.example/path?query=<script>',
|
||||
trend: trend,
|
||||
title: 'Fun'
|
||||
)
|
||||
|
||||
render partial: 'admin/trends/links/preview_card', locals: { preview_card: preview_card, f: form }
|
||||
|
||||
expect(rendered).to include('<a href="https://host.example/path?query=<script>">Fun</a>')
|
||||
end
|
||||
end
|
|
@ -13,7 +13,7 @@ describe 'statuses/show.html.haml', without_verify_partial_doubles: true do
|
|||
it 'has valid opengraph tags' do
|
||||
alice = Fabricate(:account, username: 'alice', display_name: 'Alice')
|
||||
status = Fabricate(:status, account: alice, text: 'Hello World')
|
||||
media = Fabricate(:media_attachment, account: alice, status: status, type: :video)
|
||||
Fabricate(:media_attachment, account: alice, status: status, type: :video)
|
||||
|
||||
assign(:status, status)
|
||||
assign(:account, alice)
|
||||
|
@ -32,7 +32,7 @@ describe 'statuses/show.html.haml', without_verify_partial_doubles: true do
|
|||
it 'has twitter player tag' do
|
||||
alice = Fabricate(:account, username: 'alice', display_name: 'Alice')
|
||||
status = Fabricate(:status, account: alice, text: 'Hello World')
|
||||
media = Fabricate(:media_attachment, account: alice, status: status, type: :video)
|
||||
Fabricate(:media_attachment, account: alice, status: status, type: :video)
|
||||
|
||||
assign(:status, status)
|
||||
assign(:account, alice)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue