statuses_controller_spec.rb 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. RSpec.describe Api::V1::StatusesController do
  4. render_views
  5. let(:user) { Fabricate(:user) }
  6. let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
  7. let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: scopes) }
  8. context 'with an oauth token' do
  9. before do
  10. allow(controller).to receive(:doorkeeper_token) { token }
  11. end
  12. describe 'GET #show' do
  13. let(:scopes) { 'read:statuses' }
  14. let(:status) { Fabricate(:status, account: user.account) }
  15. it 'returns http success' do
  16. get :show, params: { id: status.id }
  17. expect(response).to have_http_status(200)
  18. end
  19. context 'when post includes filtered terms' do
  20. let(:status) { Fabricate(:status, text: 'this toot is about that banned word') }
  21. before do
  22. user.account.custom_filters.create!(phrase: 'filter1', context: %w(home), action: :hide, keywords_attributes: [{ keyword: 'banned' }, { keyword: 'irrelevant' }])
  23. end
  24. it 'returns http success' do
  25. get :show, params: { id: status.id }
  26. expect(response).to have_http_status(200)
  27. end
  28. it 'returns filter information' do
  29. get :show, params: { id: status.id }
  30. json = body_as_json
  31. expect(json[:filtered][0]).to include({
  32. filter: a_hash_including({
  33. id: user.account.custom_filters.first.id.to_s,
  34. title: 'filter1',
  35. filter_action: 'hide',
  36. }),
  37. keyword_matches: ['banned'],
  38. })
  39. end
  40. end
  41. context 'when post is explicitly filtered' do
  42. let(:status) { Fabricate(:status, text: 'hello world') }
  43. before do
  44. filter = user.account.custom_filters.create!(phrase: 'filter1', context: %w(home), action: :hide)
  45. filter.statuses.create!(status_id: status.id)
  46. end
  47. it 'returns http success' do
  48. get :show, params: { id: status.id }
  49. expect(response).to have_http_status(200)
  50. end
  51. it 'returns filter information' do
  52. get :show, params: { id: status.id }
  53. json = body_as_json
  54. expect(json[:filtered][0]).to include({
  55. filter: a_hash_including({
  56. id: user.account.custom_filters.first.id.to_s,
  57. title: 'filter1',
  58. filter_action: 'hide',
  59. }),
  60. status_matches: [status.id.to_s],
  61. })
  62. end
  63. end
  64. context 'when reblog includes filtered terms' do
  65. let(:status) { Fabricate(:status, reblog: Fabricate(:status, text: 'this toot is about that banned word')) }
  66. before do
  67. user.account.custom_filters.create!(phrase: 'filter1', context: %w(home), action: :hide, keywords_attributes: [{ keyword: 'banned' }, { keyword: 'irrelevant' }])
  68. end
  69. it 'returns http success' do
  70. get :show, params: { id: status.id }
  71. expect(response).to have_http_status(200)
  72. end
  73. it 'returns filter information' do
  74. get :show, params: { id: status.id }
  75. json = body_as_json
  76. expect(json[:reblog][:filtered][0]).to include({
  77. filter: a_hash_including({
  78. id: user.account.custom_filters.first.id.to_s,
  79. title: 'filter1',
  80. filter_action: 'hide',
  81. }),
  82. keyword_matches: ['banned'],
  83. })
  84. end
  85. end
  86. end
  87. describe 'GET #context' do
  88. let(:scopes) { 'read:statuses' }
  89. let(:status) { Fabricate(:status, account: user.account) }
  90. before do
  91. Fabricate(:status, account: user.account, thread: status)
  92. end
  93. it 'returns http success' do
  94. get :context, params: { id: status.id }
  95. expect(response).to have_http_status(200)
  96. end
  97. end
  98. describe 'POST #create' do
  99. let(:scopes) { 'write:statuses' }
  100. context 'with a basic status body' do
  101. before do
  102. post :create, params: { status: 'Hello world' }
  103. end
  104. it 'returns http success' do
  105. expect(response).to have_http_status(200)
  106. end
  107. it 'returns rate limit headers' do
  108. expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
  109. expect(response.headers['X-RateLimit-Remaining']).to eq (RateLimiter::FAMILIES[:statuses][:limit] - 1).to_s
  110. end
  111. end
  112. context 'with a safeguard' do
  113. let!(:alice) { Fabricate(:account, username: 'alice') }
  114. let!(:bob) { Fabricate(:account, username: 'bob') }
  115. before do
  116. post :create, params: { status: '@alice hm, @bob is really annoying lately', allowed_mentions: [alice.id] }
  117. end
  118. it 'returns http unprocessable entity' do
  119. expect(response).to have_http_status(422)
  120. end
  121. it 'returns serialized extra accounts in body' do
  122. expect(body_as_json[:unexpected_accounts].map { |a| a.slice(:id, :acct) }).to eq [{ id: bob.id.to_s, acct: bob.acct }]
  123. end
  124. end
  125. context 'with missing parameters' do
  126. before do
  127. post :create, params: {}
  128. end
  129. it 'returns http unprocessable entity' do
  130. expect(response).to have_http_status(422)
  131. end
  132. it 'returns rate limit headers' do
  133. expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
  134. end
  135. end
  136. context 'when exceeding rate limit' do
  137. before do
  138. rate_limiter = RateLimiter.new(user.account, family: :statuses)
  139. 300.times { rate_limiter.record! }
  140. post :create, params: { status: 'Hello world' }
  141. end
  142. it 'returns http too many requests' do
  143. expect(response).to have_http_status(429)
  144. end
  145. it 'returns rate limit headers' do
  146. expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
  147. expect(response.headers['X-RateLimit-Remaining']).to eq '0'
  148. end
  149. end
  150. end
  151. describe 'DELETE #destroy' do
  152. let(:scopes) { 'write:statuses' }
  153. let(:status) { Fabricate(:status, account: user.account) }
  154. before do
  155. post :destroy, params: { id: status.id }
  156. end
  157. it 'returns http success' do
  158. expect(response).to have_http_status(200)
  159. end
  160. it 'removes the status' do
  161. expect(Status.find_by(id: status.id)).to be_nil
  162. end
  163. end
  164. describe 'PUT #update' do
  165. let(:scopes) { 'write:statuses' }
  166. let(:status) { Fabricate(:status, account: user.account) }
  167. before do
  168. put :update, params: { id: status.id, status: 'I am updated' }
  169. end
  170. it 'returns http success' do
  171. expect(response).to have_http_status(200)
  172. end
  173. it 'updates the status' do
  174. expect(status.reload.text).to eq 'I am updated'
  175. end
  176. end
  177. end
  178. context 'without an oauth token' do
  179. before do
  180. allow(controller).to receive(:doorkeeper_token).and_return(nil)
  181. end
  182. context 'with a private status' do
  183. let(:status) { Fabricate(:status, account: user.account, visibility: :private) }
  184. describe 'GET #show' do
  185. it 'returns http unauthorized' do
  186. get :show, params: { id: status.id }
  187. expect(response).to have_http_status(404)
  188. end
  189. end
  190. describe 'GET #context' do
  191. before do
  192. Fabricate(:status, account: user.account, thread: status)
  193. end
  194. it 'returns http unauthorized' do
  195. get :context, params: { id: status.id }
  196. expect(response).to have_http_status(404)
  197. end
  198. end
  199. end
  200. context 'with a public status' do
  201. let(:status) { Fabricate(:status, account: user.account, visibility: :public) }
  202. describe 'GET #show' do
  203. it 'returns http success' do
  204. get :show, params: { id: status.id }
  205. expect(response).to have_http_status(200)
  206. end
  207. end
  208. describe 'GET #context' do
  209. before do
  210. Fabricate(:status, account: user.account, thread: status)
  211. end
  212. it 'returns http success' do
  213. get :context, params: { id: status.id }
  214. expect(response).to have_http_status(200)
  215. end
  216. end
  217. end
  218. end
  219. end