Merge commit 'c9ea91f8683cd5c0cfac14071a17e3956ac6d3b0' into glitch-soc/merge-upstream

Conflicts:
- `spec/requests/api/v1/timelines/tag_spec.rb`:
  Upstream refactored this file, while we had a change to switch a default setting.
  Updated as upstream did.
- `spec/views/statuses/show.html.haml_spec.rb`:
  Upstream refactored this file, while we stubbed different methods.
  Updated as upstream did, and updated the stubs accordingly.
This commit is contained in:
Claire
2024-09-03 21:51:53 +02:00
87 changed files with 851 additions and 477 deletions

View File

@@ -14,7 +14,7 @@ describe 'The account show page' do
expect(head_meta_content('og:title')).to match alice.display_name
expect(head_meta_content('og:type')).to eq 'profile'
expect(head_meta_content('og:image')).to match '.+'
expect(head_meta_content('og:url')).to match 'http://.+'
expect(head_meta_content('og:url')).to eq short_account_url(username: alice.username)
end
def head_link_icons

View File

@@ -130,6 +130,7 @@ describe 'Accounts show response' do
it 'returns a JSON version of the account', :aggregate_failures do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
.and have_attributes(
media_type: eq('application/activity+json')
)
@@ -137,8 +138,6 @@ describe 'Accounts show response' do
expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
end
it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
context 'with authorized fetch mode' do
let(:authorized_fetch_mode) { true }
@@ -179,6 +178,7 @@ describe 'Accounts show response' do
it 'returns a JSON version of the account', :aggregate_failures do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
.and have_attributes(
media_type: eq('application/activity+json')
)
@@ -186,8 +186,6 @@ describe 'Accounts show response' do
expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
end
it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
context 'with authorized fetch mode' do
let(:authorized_fetch_mode) { true }
@@ -215,10 +213,10 @@ describe 'Accounts show response' do
get short_account_path(username: account.username, format: format)
end
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)
.to have_http_status(200)
.and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
expect(response.body).to include(status_tag_for(status_media))
expect(response.body).to include(status_tag_for(status_self_reply))
expect(response.body).to include(status_tag_for(status))
@@ -234,10 +232,11 @@ describe 'Accounts show response' do
get short_account_with_replies_path(username: account.username, format: format)
end
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)
.to have_http_status(200)
.and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
expect(response.body).to include(status_tag_for(status_media))
expect(response.body).to include(status_tag_for(status_reply))
expect(response.body).to include(status_tag_for(status_self_reply))
@@ -253,10 +252,10 @@ describe 'Accounts show response' do
get short_account_media_path(username: account.username, format: format)
end
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)
.to have_http_status(200)
.and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
expect(response.body).to include(status_tag_for(status_media))
expect(response.body).to_not include(status_tag_for(status_direct))
expect(response.body).to_not include(status_tag_for(status_private))
@@ -277,10 +276,11 @@ describe 'Accounts show response' do
get short_account_tag_path(username: account.username, tag: tag, format: format)
end
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)
.to have_http_status(200)
.and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
expect(response.body).to include(status_tag_for(status_tag))
expect(response.body).to_not include(status_tag_for(status_direct))
expect(response.body).to_not include(status_tag_for(status_media))

View File

@@ -0,0 +1,57 @@
# frozen_string_literal: true
require 'rails_helper'
describe 'API V1 Annual Reports' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
describe 'GET /api/v1/annual_reports' do
context 'when not authorized' do
it 'returns http unauthorized' do
get api_v1_annual_reports_path
expect(response)
.to have_http_status(401)
end
end
context 'with wrong scope' do
before do
get api_v1_annual_reports_path, headers: headers
end
it_behaves_like 'forbidden for wrong scope', 'write write:accounts'
end
context 'with correct scope' do
let(:scopes) { 'read:accounts' }
it 'returns http success' do
get api_v1_annual_reports_path, headers: headers
expect(response)
.to have_http_status(200)
expect(body_as_json)
.to be_present
end
end
end
describe 'POST /api/v1/annual_reports/:id/read' do
context 'with correct scope' do
let(:scopes) { 'write:accounts' }
it 'returns success and marks the report as read' do
annual_report = Fabricate :generated_annual_report, account: user.account
expect { post read_api_v1_annual_report_path(id: annual_report.year), headers: headers }
.to change { annual_report.reload.viewed? }.to(true)
expect(response)
.to have_http_status(200)
end
end
end
end

View File

@@ -10,12 +10,11 @@ describe 'API V1 Streaming' do
Rails.configuration.x.streaming_api_base_url = before
end
let(:headers) { { 'Host' => Rails.configuration.x.web_domain } }
context 'with streaming api on same host' do
describe 'GET /api/v1/streaming' do
it 'raises ActiveRecord::RecordNotFound' do
get '/api/v1/streaming', headers: headers
integration_session.https!(false)
get '/api/v1/streaming'
expect(response).to have_http_status(404)
end

View File

@@ -8,15 +8,6 @@ RSpec.describe 'Tag' do
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
shared_examples 'a successful request to the tag timeline' do
it 'returns the expected statuses', :aggregate_failures do
subject
expect(response).to have_http_status(200)
expect(body_as_json.pluck(:id)).to match_array(expected_statuses.map { |status| status.id.to_s })
end
end
describe 'GET /api/v1/timelines/tag/:hashtag' do
subject do
get "/api/v1/timelines/tag/#{hashtag}", headers: headers, params: params
@@ -26,8 +17,20 @@ RSpec.describe 'Tag' do
Setting.timeline_preview = true
end
shared_examples 'a successful request to the tag timeline' do
it 'returns the expected statuses', :aggregate_failures do
subject
expect(response)
.to have_http_status(200)
expect(body_as_json.pluck(:id))
.to match_array(expected_statuses.map { |status| status.id.to_s })
.and not_include(private_status.id)
end
end
let(:account) { Fabricate(:account) }
let!(:private_status) { PostStatusService.new.call(account, visibility: :private, text: '#life could be a dream') } # rubocop:disable RSpec/LetSetup
let!(:private_status) { PostStatusService.new.call(account, visibility: :private, text: '#life could be a dream') }
let!(:life_status) { PostStatusService.new.call(account, text: 'tell me what is my #life without your #love') }
let!(:war_status) { PostStatusService.new.call(user.account, text: '#war, war never changes') }
let!(:love_status) { PostStatusService.new.call(account, text: 'what is #love?') }

View File

@@ -0,0 +1,80 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Accounts in grouped notifications' do
let(:user) { Fabricate(:user, account_attributes: { username: 'alice' }) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read:notifications write:notifications' }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
describe 'GET /api/v2_alpha/notifications/:group_key/accounts', :inline_jobs do
subject do
get "/api/v2_alpha/notifications/#{user.account.notifications.first.group_key}/accounts", headers: headers, params: params
end
let(:params) { {} }
before do
first_status = PostStatusService.new.call(user.account, text: 'Test')
FavouriteService.new.call(Fabricate(:account), first_status)
FavouriteService.new.call(Fabricate(:account), first_status)
ReblogService.new.call(Fabricate(:account), first_status)
FollowService.new.call(Fabricate(:account), user.account)
FavouriteService.new.call(Fabricate(:account), first_status)
end
it_behaves_like 'forbidden for wrong scope', 'write write:notifications'
it 'returns a list of accounts' do
subject
expect(response).to have_http_status(200)
# The group we are interested in is only favorites
notifications = user.account.notifications.where(type: 'favourite').reorder(id: :desc)
expect(body_as_json).to match(
[
a_hash_including(
id: notifications.first.from_account_id.to_s
),
a_hash_including(
id: notifications.second.from_account_id.to_s
),
a_hash_including(
id: notifications.third.from_account_id.to_s
),
]
)
end
context 'with limit param' do
let(:params) { { limit: 2 } }
it 'returns the requested number of accounts, with pagination headers' do
subject
expect(response).to have_http_status(200)
# The group we are interested in is only favorites
notifications = user.account.notifications.where(type: 'favourite').reorder(id: :desc)
expect(body_as_json).to match(
[
a_hash_including(
id: notifications.first.from_account_id.to_s
),
a_hash_including(
id: notifications.second.from_account_id.to_s
),
]
)
expect(response)
.to include_pagination_headers(
prev: api_v2_alpha_notification_accounts_url(limit: params[:limit], min_id: notifications.first.id),
next: api_v2_alpha_notification_accounts_url(limit: params[:limit], max_id: notifications.second.id)
)
end
end
end
end

View File

@@ -9,11 +9,10 @@ describe 'Custom stylesheets' do
it 'returns http success' do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers
.and have_attributes(
content_type: match('text/css')
)
end
it_behaves_like 'cacheable response'
end
end

View File

@@ -17,6 +17,7 @@ RSpec.describe 'Instance actor endpoint' do
it 'returns http success with correct media type and body' do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers
expect(response.content_type)
.to start_with('application/activity+json')
expect(body_as_json)
@@ -32,8 +33,6 @@ RSpec.describe 'Instance actor endpoint' do
url: about_more_url(instance_actor: true)
)
end
it_behaves_like 'cacheable response'
end
context 'with limited federation mode disabled' do

View File

@@ -13,7 +13,7 @@ describe 'Link headers' do
it 'contains webfinger url in link header' do
link_header = link_header_with_type('application/jrd+json')
expect(link_header.href).to eq 'http://www.example.com/.well-known/webfinger?resource=acct%3Atest%40cb6e6126.ngrok.io'
expect(link_header.href).to eq 'https://cb6e6126.ngrok.io/.well-known/webfinger?resource=acct%3Atest%40cb6e6126.ngrok.io'
expect(link_header.attr_pairs.first).to eq %w(rel lrdd)
end

View File

@@ -9,6 +9,7 @@ describe 'Manifest' do
it 'returns http success' do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers
.and have_attributes(
content_type: match('application/json')
)
@@ -18,7 +19,5 @@ describe 'Manifest' do
name: 'Mastodon Glitch Edition'
)
end
it_behaves_like 'cacheable response'
end
end

View File

@@ -4,12 +4,7 @@ require 'rails_helper'
describe 'Media Proxy' do
describe 'GET /media_proxy/:id' do
before do
integration_session.https! # TODO: Move to global rails_helper for all request specs?
host! Rails.configuration.x.local_domain # TODO: Move to global rails_helper for all request specs?
stub_request(:get, 'http://example.com/attachment.png').to_return(request_fixture('avatar.txt'))
end
before { stub_attachment_request }
context 'when attached to a status' do
let(:status) { Fabricate(:status) }
@@ -63,5 +58,15 @@ describe 'Media Proxy' do
.to have_http_status(404)
end
end
def stub_attachment_request
stub_request(
:get,
'http://example.com/attachment.png'
)
.to_return(
request_fixture('avatar.txt')
)
end
end
end

View File

@@ -0,0 +1,56 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Tags' do
describe 'GET /tags/:id' do
context 'when tag exists' do
let(:tag) { Fabricate :tag }
context 'with HTML format' do
# TODO: Update the have_cacheable_headers matcher to operate on capybara sessions
# Remove this example, rely on system spec (which should use matcher)
before { get tag_path(tag) }
it 'returns http success' do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
end
end
context 'with JSON format' do
before { get tag_path(tag, format: :json) }
it 'returns http success' do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
expect(response.content_type)
.to start_with('application/activity+json')
end
end
context 'with RSS format' do
before { get tag_path(tag, format: :rss) }
it 'returns http success' do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
expect(response.content_type)
.to start_with('application/rss+xml')
end
end
end
context 'when tag does not exist' do
before { get tag_path('missing') }
it 'returns http not found' do
expect(response)
.to have_http_status(404)
end
end
end
end