From 7adf25f4663f8701c3f12cf61cced0c40555bce3 Mon Sep 17 00:00:00 2001 From: fusagiko / takayamaki Date: Sun, 10 May 2026 13:17:51 +0000 Subject: [PATCH 1/2] Move GET /api/v1/accounts/:id specs to accounts_show_spec.rb Wrap the existing specs in an "endpoint behavior" describe to leave room for a parallel "response keys" describe in subsequent commits. --- spec/requests/api/v1/accounts_show_spec.rb | 52 ++++++++++++++++++++++ spec/requests/api/v1/accounts_spec.rb | 46 ------------------- 2 files changed, 52 insertions(+), 46 deletions(-) create mode 100644 spec/requests/api/v1/accounts_show_spec.rb diff --git a/spec/requests/api/v1/accounts_show_spec.rb b/spec/requests/api/v1/accounts_show_spec.rb new file mode 100644 index 00000000000..b9d5a394083 --- /dev/null +++ b/spec/requests/api/v1/accounts_show_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'GET /api/v1/accounts/:id' do + describe 'endpoint behavior' do + include_context 'with API authentication', oauth_scopes: 'read:accounts' + + context 'when logged out' do + let(:account) { Fabricate(:account) } + + it 'returns account entity as 200 OK', :aggregate_failures do + get "/api/v1/accounts/#{account.id}" + + expect(response).to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body[:id]).to eq(account.id.to_s) + end + end + + context 'when the account does not exist' do + it 'returns http not found' do + get '/api/v1/accounts/1' + + expect(response).to have_http_status(404) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body[:error]).to eq('Record not found') + end + end + + context 'when logged in' do + subject do + get "/api/v1/accounts/#{account.id}", headers: headers + end + + let(:account) { Fabricate(:account) } + + it 'returns account entity as 200 OK', :aggregate_failures do + subject + + expect(response).to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body[:id]).to eq(account.id.to_s) + end + + it_behaves_like 'forbidden for wrong scope', 'write:statuses' + end + end +end diff --git a/spec/requests/api/v1/accounts_spec.rb b/spec/requests/api/v1/accounts_spec.rb index 0ea5c3921ef..15783efb720 100644 --- a/spec/requests/api/v1/accounts_spec.rb +++ b/spec/requests/api/v1/accounts_spec.rb @@ -23,52 +23,6 @@ RSpec.describe '/api/v1/accounts' do end end - describe 'GET /api/v1/accounts/:id' do - context 'when logged out' do - let(:account) { Fabricate(:account) } - - it 'returns account entity as 200 OK', :aggregate_failures do - get "/api/v1/accounts/#{account.id}" - - expect(response).to have_http_status(200) - expect(response.content_type) - .to start_with('application/json') - expect(response.parsed_body[:id]).to eq(account.id.to_s) - end - end - - context 'when the account does not exist' do - it 'returns http not found' do - get '/api/v1/accounts/1' - - expect(response).to have_http_status(404) - expect(response.content_type) - .to start_with('application/json') - expect(response.parsed_body[:error]).to eq('Record not found') - end - end - - context 'when logged in' do - subject do - get "/api/v1/accounts/#{account.id}", headers: headers - end - - let(:account) { Fabricate(:account) } - let(:scopes) { 'read:accounts' } - - it 'returns account entity as 200 OK', :aggregate_failures do - subject - - expect(response).to have_http_status(200) - expect(response.content_type) - .to start_with('application/json') - expect(response.parsed_body[:id]).to eq(account.id.to_s) - end - - it_behaves_like 'forbidden for wrong scope', 'write:statuses' - end - end - describe 'POST /api/v1/accounts' do subject do post '/api/v1/accounts', headers: headers, params: { username: 'test', password: '12345678', email: 'hello@world.tld', agreement: agreement, date_of_birth: date_of_birth } From 08de959f37e27b203b324e1363a15c556a444e32 Mon Sep 17 00:00:00 2001 From: fusagiko / takayamaki Date: Sun, 10 May 2026 13:18:39 +0000 Subject: [PATCH 2/2] Add locality-dependent response key specs to accounts show --- spec/requests/api/v1/accounts_show_spec.rb | 84 ++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/spec/requests/api/v1/accounts_show_spec.rb b/spec/requests/api/v1/accounts_show_spec.rb index b9d5a394083..45451cf4806 100644 --- a/spec/requests/api/v1/accounts_show_spec.rb +++ b/spec/requests/api/v1/accounts_show_spec.rb @@ -49,4 +49,88 @@ RSpec.describe 'GET /api/v1/accounts/:id' do it_behaves_like 'forbidden for wrong scope', 'write:statuses' end end + + describe 'response keys' do + subject { get "/api/v1/accounts/#{account.id}" } + + shared_context 'with local account' do + let(:account) { Fabricate(:account, username: 'alice') } + end + + shared_context 'with remote account' do + let(:account) { Fabricate(:remote_account, username: 'alice', domain: 'remote.example') } + end + + describe 'acct' do + context 'when local account' do + include_context 'with local account' + + it 'returns the bare username' do + subject + expect(response.parsed_body[:acct]).to eq 'alice' + end + end + + context 'when remote account' do + include_context 'with remote account' + + it 'returns username@domain' do + subject + expect(response.parsed_body[:acct]).to eq 'alice@remote.example' + end + end + end + + describe 'url' do + context 'when local account' do + include_context 'with local account' + + it 'returns the public profile URL on the local domain', :aggregate_failures do + subject + url = URI.parse(response.parsed_body[:url]) + expect(url.scheme).to eq 'https' + expect(url.host).to eq Rails.configuration.x.local_domain + expect(url.path).to eq '/@alice' + end + end + + context 'when remote account' do + include_context 'with remote account' + + it 'returns the URL preserved from the remote source', :aggregate_failures do + subject + url = URI.parse(response.parsed_body[:url]) + expect(url.scheme).to eq 'https' + expect(url.host).to eq 'remote.example' + expect(url.path).to eq '/users/alice' + end + end + end + + describe 'uri' do + context 'when local account' do + include_context 'with local account' + + it 'returns the canonical ActivityPub URI on the local domain', :aggregate_failures do + subject + uri = URI.parse(response.parsed_body[:uri]) + expect(uri.scheme).to eq 'https' + expect(uri.host).to eq Rails.configuration.x.local_domain + expect(uri.path).to eq "/ap/users/#{account.id}" + end + end + + context 'when remote account' do + include_context 'with remote account' + + it 'returns the ActivityPub URI preserved from the remote source', :aggregate_failures do + subject + uri = URI.parse(response.parsed_body[:uri]) + expect(uri.scheme).to eq 'https' + expect(uri.host).to eq 'remote.example' + expect(uri.path).to eq '/users/alice' + end + end + end + end end