accounts_spec.rb 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. describe 'Accounts show response' do
  4. let(:account) { Fabricate(:account) }
  5. context 'with an unapproved account' do
  6. before { account.user.update(approved: false) }
  7. it 'returns http not found' do
  8. %w(html json rss).each do |format|
  9. get short_account_path(username: account.username), as: format
  10. expect(response).to have_http_status(404)
  11. end
  12. end
  13. end
  14. context 'with a permanently suspended account' do
  15. before do
  16. account.suspend!
  17. account.deletion_request.destroy
  18. end
  19. it 'returns http gone' do
  20. %w(html json rss).each do |format|
  21. get short_account_path(username: account.username), as: format
  22. expect(response).to have_http_status(410)
  23. end
  24. end
  25. end
  26. context 'with a temporarily suspended account' do
  27. before { account.suspend! }
  28. it 'returns appropriate http response code' do
  29. { html: 403, json: 200, rss: 403 }.each do |format, code|
  30. get short_account_path(username: account.username), as: format
  31. expect(response).to have_http_status(code)
  32. end
  33. end
  34. end
  35. describe 'GET to short username paths' do
  36. context 'with existing statuses' do
  37. let!(:status) { Fabricate(:status, account: account) }
  38. let!(:status_reply) { Fabricate(:status, account: account, thread: Fabricate(:status)) }
  39. let!(:status_self_reply) { Fabricate(:status, account: account, thread: status) }
  40. let!(:status_media) { Fabricate(:status, account: account) }
  41. let!(:status_pinned) { Fabricate(:status, account: account) }
  42. let!(:status_private) { Fabricate(:status, account: account, visibility: :private) }
  43. let!(:status_direct) { Fabricate(:status, account: account, visibility: :direct) }
  44. let!(:status_reblog) { Fabricate(:status, account: account, reblog: Fabricate(:status)) }
  45. before do
  46. status_media.media_attachments << Fabricate(:media_attachment, account: account, type: :image)
  47. account.pinned_statuses << status_pinned
  48. account.pinned_statuses << status_private
  49. end
  50. context 'with HTML' do
  51. let(:format) { 'html' }
  52. shared_examples 'common HTML response' do
  53. it 'returns a standard HTML response', :aggregate_failures do
  54. expect(response)
  55. .to have_http_status(200)
  56. .and render_template(:show)
  57. expect(response.headers['Link'].to_s).to include ActivityPub::TagManager.instance.uri_for(account)
  58. end
  59. end
  60. context 'with a normal account in an HTML request' do
  61. before do
  62. get short_account_path(username: account.username), as: format
  63. end
  64. it_behaves_like 'common HTML response'
  65. end
  66. context 'with replies' do
  67. before do
  68. get short_account_with_replies_path(username: account.username), as: format
  69. end
  70. it_behaves_like 'common HTML response'
  71. end
  72. context 'with media' do
  73. before do
  74. get short_account_media_path(username: account.username), as: format
  75. end
  76. it_behaves_like 'common HTML response'
  77. end
  78. context 'with tag' do
  79. let(:tag) { Fabricate(:tag) }
  80. let!(:status_tag) { Fabricate(:status, account: account) }
  81. before do
  82. status_tag.tags << tag
  83. get short_account_tag_path(username: account.username, tag: tag), as: format
  84. end
  85. it_behaves_like 'common HTML response'
  86. end
  87. end
  88. context 'with JSON' do
  89. let(:authorized_fetch_mode) { false }
  90. let(:headers) { { 'ACCEPT' => 'application/json' } }
  91. around do |example|
  92. ClimateControl.modify AUTHORIZED_FETCH: authorized_fetch_mode.to_s do
  93. example.run
  94. end
  95. end
  96. context 'with a normal account in a JSON request' do
  97. before do
  98. get short_account_path(username: account.username), headers: headers
  99. end
  100. it 'returns a JSON version of the account', :aggregate_failures do
  101. expect(response)
  102. .to have_http_status(200)
  103. .and have_attributes(
  104. media_type: eq('application/activity+json')
  105. )
  106. expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
  107. end
  108. it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
  109. context 'with authorized fetch mode' do
  110. let(:authorized_fetch_mode) { true }
  111. it 'returns http unauthorized' do
  112. expect(response).to have_http_status(401)
  113. end
  114. end
  115. end
  116. context 'when signed in' do
  117. let(:user) { Fabricate(:user) }
  118. before do
  119. sign_in(user)
  120. get short_account_path(username: account.username), headers: headers.merge({ 'Cookie' => '123' })
  121. end
  122. it 'returns a private JSON version of the account', :aggregate_failures do
  123. expect(response)
  124. .to have_http_status(200)
  125. .and have_attributes(
  126. media_type: eq('application/activity+json')
  127. )
  128. expect(response.headers['Cache-Control']).to include 'private'
  129. expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
  130. end
  131. end
  132. context 'with signature' do
  133. let(:remote_account) { Fabricate(:account, domain: 'example.com') }
  134. before do
  135. get short_account_path(username: account.username), headers: headers, sign_with: remote_account
  136. end
  137. it 'returns a JSON version of the account', :aggregate_failures do
  138. expect(response)
  139. .to have_http_status(200)
  140. .and have_attributes(
  141. media_type: eq('application/activity+json')
  142. )
  143. expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
  144. end
  145. it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
  146. context 'with authorized fetch mode' do
  147. let(:authorized_fetch_mode) { true }
  148. it 'returns a private signature JSON version of the account', :aggregate_failures do
  149. expect(response)
  150. .to have_http_status(200)
  151. .and have_attributes(
  152. media_type: eq('application/activity+json')
  153. )
  154. expect(response.headers['Cache-Control']).to include 'private'
  155. expect(response.headers['Vary']).to include 'Signature'
  156. expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
  157. end
  158. end
  159. end
  160. end
  161. context 'with RSS' do
  162. let(:format) { 'rss' }
  163. context 'with a normal account in an RSS request' do
  164. before do
  165. get short_account_path(username: account.username, format: format)
  166. end
  167. it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
  168. it 'responds with correct statuses', :aggregate_failures do
  169. expect(response).to have_http_status(200)
  170. expect(response.body).to include(status_tag_for(status_media))
  171. expect(response.body).to include(status_tag_for(status_self_reply))
  172. expect(response.body).to include(status_tag_for(status))
  173. expect(response.body).to_not include(status_tag_for(status_direct))
  174. expect(response.body).to_not include(status_tag_for(status_private))
  175. expect(response.body).to_not include(status_tag_for(status_reblog.reblog))
  176. expect(response.body).to_not include(status_tag_for(status_reply))
  177. end
  178. end
  179. context 'with replies' do
  180. before do
  181. get short_account_with_replies_path(username: account.username, format: format)
  182. end
  183. it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
  184. it 'responds with correct statuses with replies', :aggregate_failures do
  185. expect(response).to have_http_status(200)
  186. expect(response.body).to include(status_tag_for(status_media))
  187. expect(response.body).to include(status_tag_for(status_reply))
  188. expect(response.body).to include(status_tag_for(status_self_reply))
  189. expect(response.body).to include(status_tag_for(status))
  190. expect(response.body).to_not include(status_tag_for(status_direct))
  191. expect(response.body).to_not include(status_tag_for(status_private))
  192. expect(response.body).to_not include(status_tag_for(status_reblog.reblog))
  193. end
  194. end
  195. context 'with media' do
  196. before do
  197. get short_account_media_path(username: account.username, format: format)
  198. end
  199. it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
  200. it 'responds with correct statuses with media', :aggregate_failures do
  201. expect(response).to have_http_status(200)
  202. expect(response.body).to include(status_tag_for(status_media))
  203. expect(response.body).to_not include(status_tag_for(status_direct))
  204. expect(response.body).to_not include(status_tag_for(status_private))
  205. expect(response.body).to_not include(status_tag_for(status_reblog.reblog))
  206. expect(response.body).to_not include(status_tag_for(status_reply))
  207. expect(response.body).to_not include(status_tag_for(status_self_reply))
  208. expect(response.body).to_not include(status_tag_for(status))
  209. end
  210. end
  211. context 'with tag' do
  212. let(:tag) { Fabricate(:tag) }
  213. let!(:status_tag) { Fabricate(:status, account: account) }
  214. before do
  215. status_tag.tags << tag
  216. get short_account_tag_path(username: account.username, tag: tag, format: format)
  217. end
  218. it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
  219. it 'responds with correct statuses with a tag', :aggregate_failures do
  220. expect(response).to have_http_status(200)
  221. expect(response.body).to include(status_tag_for(status_tag))
  222. expect(response.body).to_not include(status_tag_for(status_direct))
  223. expect(response.body).to_not include(status_tag_for(status_media))
  224. expect(response.body).to_not include(status_tag_for(status_private))
  225. expect(response.body).to_not include(status_tag_for(status_reblog.reblog))
  226. expect(response.body).to_not include(status_tag_for(status_reply))
  227. expect(response.body).to_not include(status_tag_for(status_self_reply))
  228. expect(response.body).to_not include(status_tag_for(status))
  229. end
  230. end
  231. end
  232. end
  233. end
  234. def status_tag_for(status)
  235. ActivityPub::TagManager.instance.url_for(status)
  236. end
  237. end