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

This commit is contained in:
KMY 2023-11-10 09:02:03 +09:00
commit bfc7b0101d
44 changed files with 992 additions and 744 deletions

View file

@ -7,66 +7,44 @@ RSpec.describe AccountsController do
let(:account) { Fabricate(:account) }
shared_examples 'unapproved account check' do
describe 'unapproved account check' do
before { account.user.update(approved: false) }
it 'returns http not found' do
get :show, params: { username: account.username, format: format }
expect(response).to have_http_status(404)
%w(html json rss).each do |format|
get :show, params: { username: account.username, format: format }
expect(response).to have_http_status(404)
end
end
end
shared_examples 'permanently suspended account check' do
describe 'permanently suspended account check' do
before do
account.suspend!
account.deletion_request.destroy
end
it 'returns http gone' do
get :show, params: { username: account.username, format: format }
expect(response).to have_http_status(410)
%w(html json rss).each do |format|
get :show, params: { username: account.username, format: format }
expect(response).to have_http_status(410)
end
end
end
shared_examples 'temporarily suspended account check' do |code: 403|
describe 'temporarily suspended account check' do
before { account.suspend! }
it 'returns appropriate http response code' do
get :show, params: { username: account.username, format: format }
{ html: 403, json: 200, rss: 403 }.each do |format, code|
get :show, params: { username: account.username, format: format }
expect(response).to have_http_status(code)
expect(response).to have_http_status(code)
end
end
end
describe 'GET #show' do
context 'with basic account status checks' do
context 'with HTML' do
let(:format) { 'html' }
it_behaves_like 'unapproved account check'
it_behaves_like 'permanently suspended account check'
it_behaves_like 'temporarily suspended account check'
end
context 'with JSON' do
let(:format) { 'json' }
it_behaves_like 'unapproved account check'
it_behaves_like 'permanently suspended account check'
it_behaves_like 'temporarily suspended account check', code: 200
end
context 'with RSS' do
let(:format) { 'rss' }
it_behaves_like 'unapproved account check'
it_behaves_like 'permanently suspended account check'
it_behaves_like 'temporarily suspended account check'
end
end
context 'with existing statuses' do
let!(:status) { Fabricate(:status, account: account) }
let!(:status_reply) { Fabricate(:status, account: account, thread: Fabricate(:status)) }
@ -227,22 +205,15 @@ RSpec.describe AccountsController do
context 'with RSS' do
let(:format) { 'rss' }
shared_examples 'common RSS response' do
it 'returns http success' do
expect(response).to have_http_status(200)
end
it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
end
context 'with a normal account in an RSS request' do
before do
get :show, params: { username: account.username, format: format }
end
it_behaves_like 'common RSS response'
it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
it 'responds with correct statuses', :aggregate_failures do
expect(response).to have_http_status(200)
expect(response.body).to include_status_tag(status_media)
expect(response.body).to include_status_tag(status_self_reply)
expect(response.body).to include_status_tag(status)
@ -259,9 +230,10 @@ RSpec.describe AccountsController do
get :show, params: { username: account.username, format: format }
end
it_behaves_like 'common RSS response'
it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
it 'responds with correct statuses with replies', :aggregate_failures do
expect(response).to have_http_status(200)
expect(response.body).to include_status_tag(status_media)
expect(response.body).to include_status_tag(status_reply)
expect(response.body).to include_status_tag(status_self_reply)
@ -278,9 +250,10 @@ RSpec.describe AccountsController do
get :show, params: { username: account.username, format: format }
end
it_behaves_like 'common RSS response'
it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
it 'responds with correct statuses with media', :aggregate_failures do
expect(response).to have_http_status(200)
expect(response.body).to include_status_tag(status_media)
expect(response.body).to_not include_status_tag(status_direct)
expect(response.body).to_not include_status_tag(status_private)
@ -302,9 +275,10 @@ RSpec.describe AccountsController do
get :show, params: { username: account.username, format: format, tag: tag.to_param }
end
it_behaves_like 'common RSS response'
it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
it 'responds with correct statuses with a tag', :aggregate_failures do
expect(response).to have_http_status(200)
expect(response.body).to include_status_tag(status_tag)
expect(response.body).to_not include_status_tag(status_direct)
expect(response.body).to_not include_status_tag(status_media)

View file

@ -1,102 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
describe Api::V1::Accounts::RelationshipsController do
render_views
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:follows') }
before do
allow(controller).to receive(:doorkeeper_token) { token }
end
describe 'GET #index' do
let(:simon) { Fabricate(:account) }
let(:lewis) { Fabricate(:account) }
before do
user.account.follow!(simon)
lewis.follow!(user.account)
end
context 'when provided only one ID' do
before do
get :index, params: { id: simon.id }
end
it 'returns JSON with correct data', :aggregate_failures do
json = body_as_json
expect(response).to have_http_status(200)
expect(json).to be_a Enumerable
expect(json.first[:following]).to be true
expect(json.first[:followed_by]).to be false
end
end
context 'when provided multiple IDs' do
before do
get :index, params: { id: [simon.id, lewis.id] }
end
it 'returns http success' do
expect(response).to have_http_status(200)
end
context 'when there is returned JSON data' do
let(:json) { body_as_json }
it 'returns an enumerable json with correct elements', :aggregate_failures do
expect(json).to be_a Enumerable
expect_simon_item_one
expect_lewis_item_two
end
def expect_simon_item_one
expect(json.first[:id]).to eq simon.id.to_s
expect(json.first[:following]).to be true
expect(json.first[:showing_reblogs]).to be true
expect(json.first[:followed_by]).to be false
expect(json.first[:muting]).to be false
expect(json.first[:requested]).to be false
expect(json.first[:domain_blocking]).to be false
end
def expect_lewis_item_two
expect(json.second[:id]).to eq lewis.id.to_s
expect(json.second[:following]).to be false
expect(json.second[:showing_reblogs]).to be false
expect(json.second[:followed_by]).to be true
expect(json.second[:muting]).to be false
expect(json.second[:requested]).to be false
expect(json.second[:domain_blocking]).to be false
end
end
it 'returns JSON with correct data on cached requests too' do
get :index, params: { id: [simon.id] }
json = body_as_json
expect(json).to be_a Enumerable
expect(json.first[:following]).to be true
expect(json.first[:showing_reblogs]).to be true
end
it 'returns JSON with correct data after change too' do
user.account.unfollow!(simon)
get :index, params: { id: [simon.id] }
json = body_as_json
expect(json).to be_a Enumerable
expect(json.first[:following]).to be false
expect(json.first[:showing_reblogs]).to be false
end
end
end
end

View file

@ -2,5 +2,5 @@
Fabricator(:session_activation) do
user { Fabricate.build(:user) }
session_id 'MyString'
session_id { sequence(:session_id) { |i| "session_id_#{i}" } }
end

View file

@ -296,5 +296,51 @@ describe ApplicationHelper do
expect(helper.title).to eq 'site title'
expect(Rails.env).to have_received(:production?)
end
it 'returns site title with note on non-production environment' do
Setting.site_title = 'site title'
allow(Rails.env).to receive(:production?).and_return(false)
expect(helper.title).to eq 'site title (Dev)'
expect(Rails.env).to have_received(:production?)
end
end
describe 'html_title' do
before do
allow(Rails.env).to receive(:production?).and_return(true)
end
around do |example|
site_title = Setting.site_title
example.run
Setting.site_title = site_title
end
context 'with a page_title content_for value' do
it 'uses the value in the html title' do
Setting.site_title = 'Site Title'
helper.content_for(:page_title, 'Test Value')
expect(helper.html_title).to eq 'Test Value - Site Title'
expect(helper.html_title).to be_html_safe
end
it 'removes extra new lines' do
Setting.site_title = 'Site Title'
helper.content_for(:page_title, "Test Value\n")
expect(helper.html_title).to eq 'Test Value - Site Title'
expect(helper.html_title).to be_html_safe
end
end
context 'without any page_title content_for value' do
it 'returns the site title' do
Setting.site_title = 'Site Title'
expect(helper.html_title).to eq 'Site Title'
expect(helper.html_title).to be_html_safe
end
end
end
end

View file

@ -4,16 +4,23 @@ require 'rails_helper'
describe FlashesHelper do
describe 'user_facing_flashes' do
it 'returns user facing flashes' do
before do
# rubocop:disable Rails/I18nLocaleTexts
flash[:alert] = 'an alert'
flash[:error] = 'an error'
flash[:notice] = 'a notice'
flash[:success] = 'a success'
flash[:not_user_facing] = 'a not user facing flash'
expect(helper.user_facing_flashes).to eq 'alert' => 'an alert',
'error' => 'an error',
'notice' => 'a notice',
'success' => 'a success'
# rubocop:enable Rails/I18nLocaleTexts
end
it 'returns user facing flashes' do
expect(helper.user_facing_flashes).to eq(
'alert' => 'an alert',
'error' => 'an error',
'notice' => 'a notice',
'success' => 'a success'
)
end
end
end

View file

@ -69,7 +69,9 @@ RSpec.describe Remotable do
context 'with an invalid URL' do
before do
allow(Addressable::URI).to receive_message_chain(:parse, :normalize).with(url).with(no_args).and_raise(Addressable::URI::InvalidURIError)
parsed = instance_double(Addressable::URI)
allow(parsed).to receive(:normalize).with(no_args).and_raise(Addressable::URI::InvalidURIError)
allow(Addressable::URI).to receive(:parse).with(url).and_return(parsed)
end
it 'makes no request' do

View file

@ -98,34 +98,44 @@ RSpec.describe SessionActivation do
end
context 'when id exists' do
let(:id) { '1' }
let!(:session_activation) { Fabricate(:session_activation) }
it 'calls where.destroy_all' do
expect(described_class).to receive_message_chain(:where, :destroy_all)
.with(session_id: id).with(no_args)
it 'destroys the record' do
described_class.deactivate(session_activation.session_id)
described_class.deactivate(id)
expect { session_activation.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
end
end
describe '.purge_old' do
it 'calls order.offset.destroy_all' do
expect(described_class).to receive_message_chain(:order, :offset, :destroy_all)
.with('created_at desc').with(Rails.configuration.x.max_session_activations).with(no_args)
around do |example|
before = Rails.configuration.x.max_session_activations
Rails.configuration.x.max_session_activations = 1
example.run
Rails.configuration.x.max_session_activations = before
end
let!(:oldest_session_activation) { Fabricate(:session_activation, created_at: 10.days.ago) }
let!(:newest_session_activation) { Fabricate(:session_activation, created_at: 5.days.ago) }
it 'preserves the newest X records based on config' do
described_class.purge_old
expect { oldest_session_activation.reload }.to raise_error(ActiveRecord::RecordNotFound)
expect { newest_session_activation.reload }.to_not raise_error
end
end
describe '.exclusive' do
let(:id) { '1' }
let!(:unwanted_session_activation) { Fabricate(:session_activation) }
let!(:wanted_session_activation) { Fabricate(:session_activation) }
it 'calls where.destroy_all' do
expect(described_class).to receive_message_chain(:where, :not, :destroy_all)
.with(session_id: id).with(no_args)
it 'preserves supplied record and destroys all others' do
described_class.exclusive(wanted_session_activation.session_id)
described_class.exclusive(id)
expect { unwanted_session_activation.reload }.to raise_error(ActiveRecord::RecordNotFound)
expect { wanted_session_activation.reload }.to_not raise_error
end
end
end

View file

@ -77,10 +77,13 @@ RSpec.describe Setting do
let(:default_value) { { default_value: 'default_value' } }
it 'calls default_value.with_indifferent_access.merge!' do
expect(default_value).to receive_message_chain(:with_indifferent_access, :merge!)
.with(db_val.value)
indifferent_hash = instance_double(Hash, merge!: nil)
allow(default_value).to receive(:with_indifferent_access).and_return(indifferent_hash)
described_class[key]
expect(default_value).to have_received(:with_indifferent_access)
expect(indifferent_hash).to have_received(:merge!).with(db_val.value)
end
end

View file

@ -0,0 +1,133 @@
# frozen_string_literal: true
require 'rails_helper'
describe 'GET /api/v1/accounts/relationships' do
subject do
get '/api/v1/accounts/relationships', headers: headers, params: params
end
let(:user) { Fabricate(:user) }
let(:scopes) { 'read:follows' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
let(:simon) { Fabricate(:account) }
let(:lewis) { Fabricate(:account) }
let(:bob) { Fabricate(:account, suspended: true) }
before do
user.account.follow!(simon)
lewis.follow!(user.account)
end
context 'when provided only one ID' do
let(:params) { { id: simon.id } }
it 'returns JSON with correct data', :aggregate_failures do
subject
json = body_as_json
expect(response).to have_http_status(200)
expect(json).to be_a Enumerable
expect(json.first[:following]).to be true
expect(json.first[:followed_by]).to be false
end
end
context 'when provided multiple IDs' do
let(:params) { { id: [simon.id, lewis.id, bob.id] } }
context 'when there is returned JSON data' do
let(:json) { body_as_json }
context 'with default parameters' do
it 'returns an enumerable json with correct elements, excluding suspended accounts', :aggregate_failures do
subject
expect(response).to have_http_status(200)
expect(json).to be_a Enumerable
expect(json.size).to eq 2
expect_simon_item_one
expect_lewis_item_two
end
end
context 'with `with_suspended` parameter' do
let(:params) { { id: [simon.id, lewis.id, bob.id], with_suspended: true } }
it 'returns an enumerable json with correct elements, including suspended accounts', :aggregate_failures do
subject
expect(response).to have_http_status(200)
expect(json).to be_a Enumerable
expect(json.size).to eq 3
expect_simon_item_one
expect_lewis_item_two
expect_bob_item_three
end
end
def expect_simon_item_one
expect(json.first[:id]).to eq simon.id.to_s
expect(json.first[:following]).to be true
expect(json.first[:showing_reblogs]).to be true
expect(json.first[:followed_by]).to be false
expect(json.first[:muting]).to be false
expect(json.first[:requested]).to be false
expect(json.first[:domain_blocking]).to be false
end
def expect_lewis_item_two
expect(json.second[:id]).to eq lewis.id.to_s
expect(json.second[:following]).to be false
expect(json.second[:showing_reblogs]).to be false
expect(json.second[:followed_by]).to be true
expect(json.second[:muting]).to be false
expect(json.second[:requested]).to be false
expect(json.second[:domain_blocking]).to be false
end
def expect_bob_item_three
expect(json.third[:id]).to eq bob.id.to_s
expect(json.third[:following]).to be false
expect(json.third[:showing_reblogs]).to be false
expect(json.third[:followed_by]).to be false
expect(json.third[:muting]).to be false
expect(json.third[:requested]).to be false
expect(json.third[:domain_blocking]).to be false
end
end
it 'returns JSON with correct data on cached requests too' do
subject
subject
expect(response).to have_http_status(200)
json = body_as_json
expect(json).to be_a Enumerable
expect(json.first[:following]).to be true
expect(json.first[:showing_reblogs]).to be true
end
it 'returns JSON with correct data after change too' do
subject
user.account.unfollow!(simon)
get '/api/v1/accounts/relationships', headers: headers, params: { id: [simon.id] }
expect(response).to have_http_status(200)
json = body_as_json
expect(json).to be_a Enumerable
expect(json.first[:following]).to be false
expect(json.first[:showing_reblogs]).to be false
end
end
end