logo

mastofe

My custom branche(s) on git.pleroma.social/pleroma/mastofe
commit: 4f9b7432dd4d323ac6cc4efceeae2efaffe62e7d
parent: 3f75f522856954690d92358107e78bafd0db0baa
Author: Eugen Rochko <eugen@zeonfederated.com>
Date:   Tue, 27 Sep 2016 16:58:23 +0200

Fix #52 - Add API versioning (v1)

Diffstat:

Mapp/assets/javascripts/components/actions/accounts.jsx10+++++-----
Mapp/assets/javascripts/components/actions/compose.jsx4++--
Mapp/assets/javascripts/components/actions/follow.jsx2+-
Mapp/assets/javascripts/components/actions/interactions.jsx8++++----
Mapp/assets/javascripts/components/actions/statuses.jsx2+-
Mapp/assets/javascripts/components/actions/timelines.jsx4++--
Dapp/controllers/api/accounts_controller.rb52----------------------------------------------------
Dapp/controllers/api/apps_controller.rb13-------------
Dapp/controllers/api/follows_controller.rb13-------------
Dapp/controllers/api/media_controller.rb8--------
Dapp/controllers/api/statuses_controller.rb54------------------------------------------------------
Aapp/controllers/api/v1/accounts_controller.rb52++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/controllers/api/v1/apps_controller.rb13+++++++++++++
Aapp/controllers/api/v1/follows_controller.rb13+++++++++++++
Aapp/controllers/api/v1/media_controller.rb8++++++++
Aapp/controllers/api/v1/statuses_controller.rb54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dapp/helpers/api/accounts_helper.rb2--
Dapp/helpers/api/apps_helper.rb2--
Dapp/helpers/api/follows_helper.rb2--
Dapp/helpers/api/media_helper.rb2--
Dapp/helpers/api/salmon_helper.rb2--
Dapp/helpers/api/statuses_helper.rb2--
Dapp/helpers/api/subscriptions_helper.rb2--
Mapp/helpers/home_helper.rb6+++---
Mapp/lib/feed_manager.rb2+-
Dapp/views/api/accounts/followers.rabl2--
Dapp/views/api/accounts/following.rabl2--
Dapp/views/api/accounts/relationships.rabl2--
Dapp/views/api/accounts/statuses.rabl2--
Dapp/views/api/follows/show.rabl2--
Dapp/views/api/statuses/context.rabl13-------------
Dapp/views/api/statuses/home.rabl2--
Dapp/views/api/statuses/mentions.rabl2--
Dapp/views/api/statuses/show.rabl31-------------------------------
Aapp/views/api/v1/accounts/followers.rabl2++
Aapp/views/api/v1/accounts/following.rabl2++
Rapp/views/api/accounts/relationship.rabl -> app/views/api/v1/accounts/relationship.rabl0
Aapp/views/api/v1/accounts/relationships.rabl2++
Rapp/views/api/accounts/show.rabl -> app/views/api/v1/accounts/show.rabl0
Aapp/views/api/v1/accounts/statuses.rabl2++
Rapp/views/api/apps/create.rabl -> app/views/api/v1/apps/create.rabl0
Aapp/views/api/v1/follows/show.rabl2++
Rapp/views/api/media/create.rabl -> app/views/api/v1/media/create.rabl0
Aapp/views/api/v1/statuses/context.rabl13+++++++++++++
Aapp/views/api/v1/statuses/home.rabl2++
Aapp/views/api/v1/statuses/mentions.rabl2++
Aapp/views/api/v1/statuses/show.rabl31+++++++++++++++++++++++++++++++
Mconfig/routes.rb62++++++++++++++++++++++++++++++++------------------------------
Dspec/controllers/api/accounts_controller_spec.rb116-------------------------------------------------------------------------------
Dspec/controllers/api/apps_controller_spec.rb26--------------------------
Dspec/controllers/api/follows_controller_spec.rb50--------------------------------------------------
Dspec/controllers/api/media_controller_spec.rb58----------------------------------------------------------
Dspec/controllers/api/statuses_controller_spec.rb173-------------------------------------------------------------------------------
Aspec/controllers/api/v1/accounts_controller_spec.rb116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aspec/controllers/api/v1/apps_controller_spec.rb26++++++++++++++++++++++++++
Aspec/controllers/api/v1/follows_controller_spec.rb50++++++++++++++++++++++++++++++++++++++++++++++++++
Aspec/controllers/api/v1/media_controller_spec.rb58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aspec/controllers/api/v1/statuses_controller_spec.rb173+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dspec/helpers/api/accounts_helper_spec.rb5-----
Dspec/helpers/api/apps_helper_spec.rb15---------------
Dspec/helpers/api/follows_helper_spec.rb5-----
Dspec/helpers/api/media_helper_spec.rb5-----
Dspec/helpers/api/salmon_helper_spec.rb5-----
Dspec/helpers/api/statuses_helper_spec.rb5-----
Dspec/helpers/api/subscriptions_helper_spec.rb5-----
65 files changed, 672 insertions(+), 729 deletions(-)

diff --git a/app/assets/javascripts/components/actions/accounts.jsx b/app/assets/javascripts/components/actions/accounts.jsx @@ -36,7 +36,7 @@ export function fetchAccount(id) { dispatch(fetchAccountRequest(id)); - axios.all([boundApi.get(`/api/accounts/${id}`), boundApi.get(`/api/accounts/relationships?id=${id}`)]).then(values => { + axios.all([boundApi.get(`/api/v1/accounts/${id}`), boundApi.get(`/api/v1/accounts/relationships?id=${id}`)]).then(values => { dispatch(fetchAccountSuccess(values[0].data, values[1].data[0])); }).catch(error => { dispatch(fetchAccountFail(id, error)); @@ -48,7 +48,7 @@ export function fetchAccountTimeline(id) { return (dispatch, getState) => { dispatch(fetchAccountTimelineRequest(id)); - api(getState).get(`/api/accounts/${id}/statuses`).then(response => { + api(getState).get(`/api/v1/accounts/${id}/statuses`).then(response => { dispatch(fetchAccountTimelineSuccess(id, response.data)); }).catch(error => { dispatch(fetchAccountTimelineFail(id, error)); @@ -62,7 +62,7 @@ export function expandAccountTimeline(id) { dispatch(expandAccountTimelineRequest(id)); - api(getState).get(`/api/accounts/${id}/statuses?max_id=${lastId}`).then(response => { + api(getState).get(`/api/v1/accounts/${id}/statuses?max_id=${lastId}`).then(response => { dispatch(expandAccountTimelineSuccess(id, response.data)); }).catch(error => { dispatch(expandAccountTimelineFail(id, error)); @@ -97,7 +97,7 @@ export function followAccount(id) { return (dispatch, getState) => { dispatch(followAccountRequest(id)); - api(getState).post(`/api/accounts/${id}/follow`).then(response => { + api(getState).post(`/api/v1/accounts/${id}/follow`).then(response => { dispatch(followAccountSuccess(response.data)); }).catch(error => { dispatch(followAccountFail(error)); @@ -109,7 +109,7 @@ export function unfollowAccount(id) { return (dispatch, getState) => { dispatch(unfollowAccountRequest(id)); - api(getState).post(`/api/accounts/${id}/unfollow`).then(response => { + api(getState).post(`/api/v1/accounts/${id}/unfollow`).then(response => { dispatch(unfollowAccountSuccess(response.data)); }).catch(error => { dispatch(unfollowAccountFail(error)); diff --git a/app/assets/javascripts/components/actions/compose.jsx b/app/assets/javascripts/components/actions/compose.jsx @@ -36,7 +36,7 @@ export function submitCompose() { return function (dispatch, getState) { dispatch(submitComposeRequest()); - api(getState).post('/api/statuses', { + api(getState).post('/api/v1/statuses', { status: getState().getIn(['compose', 'text'], ''), in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null), media_ids: getState().getIn(['compose', 'media_attachments']).map(item => item.get('id')) @@ -75,7 +75,7 @@ export function uploadCompose(files) { let data = new FormData(); data.append('file', files[0]); - api(getState).post('/api/media', data, { + api(getState).post('/api/v1/media', data, { onUploadProgress: function (e) { dispatch(uploadComposeProgress(e.loaded, e.total)); } diff --git a/app/assets/javascripts/components/actions/follow.jsx b/app/assets/javascripts/components/actions/follow.jsx @@ -16,7 +16,7 @@ export function submitFollow(router) { return function (dispatch, getState) { dispatch(submitFollowRequest()); - api(getState).post('/api/follows', { + api(getState).post('/api/v1/follows', { uri: getState().getIn(['follow', 'text']) }).then(function (response) { dispatch(submitFollowSuccess(response.data)); diff --git a/app/assets/javascripts/components/actions/interactions.jsx b/app/assets/javascripts/components/actions/interactions.jsx @@ -12,7 +12,7 @@ export function reblog(status) { return function (dispatch, getState) { dispatch(reblogRequest(status)); - api(getState).post(`/api/statuses/${status.get('id')}/reblog`).then(function (response) { + api(getState).post(`/api/v1/statuses/${status.get('id')}/reblog`).then(function (response) { // The reblog API method returns a new status wrapped around the original. In this case we are only // interested in how the original is modified, hence passing it skipping the wrapper dispatch(reblogSuccess(status, response.data.reblog)); @@ -24,7 +24,7 @@ export function reblog(status) { export function unreblog(status) { return (dispatch, getState) => { - api(getState).post(`/api/statuses/${status.get('id')}/unreblog`).then(response => { + api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then(response => { // }).catch(error => { // @@ -59,7 +59,7 @@ export function favourite(status) { return function (dispatch, getState) { dispatch(favouriteRequest(status)); - api(getState).post(`/api/statuses/${status.get('id')}/favourite`).then(function (response) { + api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then(function (response) { dispatch(favouriteSuccess(status, response.data)); }).catch(function (error) { dispatch(favouriteFail(status, error)); @@ -69,7 +69,7 @@ export function favourite(status) { export function unfavourite(status) { return (dispatch, getState) => { - api(getState).post(`/api/statuses/${status.get('id')}/unfavourite`).then(response => { + api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then(response => { // }).catch(error => { // diff --git a/app/assets/javascripts/components/actions/statuses.jsx b/app/assets/javascripts/components/actions/statuses.jsx @@ -18,7 +18,7 @@ export function fetchStatus(id) { dispatch(fetchStatusRequest(id)); - axios.all([boundApi.get(`/api/statuses/${id}`), boundApi.get(`/api/statuses/${id}/context`)]).then(values => { + axios.all([boundApi.get(`/api/v1/statuses/${id}`), boundApi.get(`/api/v1/statuses/${id}/context`)]).then(values => { dispatch(fetchStatusSuccess(values[0].data, values[1].data)); }).catch(error => { dispatch(fetchStatusFail(id, error)); diff --git a/app/assets/javascripts/components/actions/timelines.jsx b/app/assets/javascripts/components/actions/timelines.jsx @@ -45,7 +45,7 @@ export function refreshTimeline(timeline) { return function (dispatch, getState) { dispatch(refreshTimelineRequest(timeline)); - api(getState).get(`/api/statuses/${timeline}`).then(function (response) { + api(getState).get(`/api/v1/statuses/${timeline}`).then(function (response) { dispatch(refreshTimelineSuccess(timeline, response.data)); }).catch(function (error) { dispatch(refreshTimelineFail(timeline, error)); @@ -67,7 +67,7 @@ export function expandTimeline(timeline) { dispatch(expandTimelineRequest(timeline)); - api(getState).get(`/api/statuses/${timeline}?max_id=${lastId}`).then(response => { + api(getState).get(`/api/v1/statuses/${timeline}?max_id=${lastId}`).then(response => { dispatch(expandTimelineSuccess(timeline, response.data)); }).catch(error => { dispatch(expandTimelineFail(timeline, error)); diff --git a/app/controllers/api/accounts_controller.rb b/app/controllers/api/accounts_controller.rb @@ -1,52 +0,0 @@ -class Api::AccountsController < ApiController - before_action :doorkeeper_authorize! - before_action :set_account - respond_to :json - - def show - end - - def following - @following = @account.following - end - - def followers - @followers = @account.followers - end - - def statuses - @statuses = @account.statuses.with_includes.with_counters.paginate_by_max_id(20, params[:max_id] || nil).to_a - end - - def follow - @follow = FollowService.new.(current_user.account, @account.acct) - set_relationship - render action: :relationship - end - - def unfollow - @unfollow = UnfollowService.new.(current_user.account, @account) - set_relationship - render action: :relationship - end - - def relationships - ids = params[:id].is_a?(Enumerable) ? params[:id].map { |id| id.to_i } : [params[:id].to_i] - @accounts = Account.find(ids) - @following = Account.following_map(ids, current_user.account_id) - @followed_by = Account.followed_by_map(ids, current_user.account_id) - @blocking = {} - end - - private - - def set_account - @account = Account.find(params[:id]) - end - - def set_relationship - @following = Account.following_map([@account.id], current_user.account_id) - @followed_by = Account.followed_by_map([@account.id], current_user.account_id) - @blocking = {} - end -end diff --git a/app/controllers/api/apps_controller.rb b/app/controllers/api/apps_controller.rb @@ -1,13 +0,0 @@ -class Api::AppsController < ApplicationController - respond_to :json - - def create - @app = Doorkeeper::Application.create!(app_params) - end - - private - - def app_params - params.permit(:name, :redirect_uri) - end -end diff --git a/app/controllers/api/follows_controller.rb b/app/controllers/api/follows_controller.rb @@ -1,13 +0,0 @@ -class Api::FollowsController < ApiController - before_action :doorkeeper_authorize! - respond_to :json - - def create - if params[:uri].blank? - raise ActiveRecord::RecordNotFound - end - - @account = FollowService.new.(current_user.account, params[:uri]).try(:target_account) - render action: :show - end -end diff --git a/app/controllers/api/media_controller.rb b/app/controllers/api/media_controller.rb @@ -1,8 +0,0 @@ -class Api::MediaController < ApiController - before_action :doorkeeper_authorize! - respond_to :json - - def create - @media = MediaAttachment.create!(account: current_user.account, file: params[:file]) - end -end diff --git a/app/controllers/api/statuses_controller.rb b/app/controllers/api/statuses_controller.rb @@ -1,54 +0,0 @@ -class Api::StatusesController < ApiController - before_action :doorkeeper_authorize! - respond_to :json - - def show - @status = Status.find(params[:id]) - end - - def context - @status = Status.find(params[:id]) - @ancestors = @status.ancestors - @descendants = @status.descendants - end - - def create - @status = PostStatusService.new.(current_user.account, params[:status], params[:in_reply_to_id].blank? ? nil : Status.find(params[:in_reply_to_id]), params[:media_ids]) - render action: :show - end - - def destroy - @status = Status.where(account_id: current_user.account).find(params[:id]) - RemoveStatusService.new.(@status) - render_empty - end - - def reblog - @status = ReblogService.new.(current_user.account, Status.find(params[:id])).reload - render action: :show - end - - def unreblog - RemoveStatusService.new.(Status.where(account_id: current_user.account, reblog_of_id: params[:id]).first!) - @status = Status.find(params[:id]) - render action: :show - end - - def favourite - @status = FavouriteService.new.(current_user.account, Status.find(params[:id])).status.reload - render action: :show - end - - def unfavourite - @status = UnfavouriteService.new.(current_user.account, Status.find(params[:id])).status.reload - render action: :show - end - - def home - @statuses = Feed.new(:home, current_user.account).get(20, params[:max_id]).to_a - end - - def mentions - @statuses = Feed.new(:mentions, current_user.account).get(20, params[:max_id]).to_a - end -end diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb @@ -0,0 +1,52 @@ +class Api::V1::AccountsController < ApiController + before_action :doorkeeper_authorize! + before_action :set_account + respond_to :json + + def show + end + + def following + @following = @account.following + end + + def followers + @followers = @account.followers + end + + def statuses + @statuses = @account.statuses.with_includes.with_counters.paginate_by_max_id(20, params[:max_id] || nil).to_a + end + + def follow + @follow = FollowService.new.(current_user.account, @account.acct) + set_relationship + render action: :relationship + end + + def unfollow + @unfollow = UnfollowService.new.(current_user.account, @account) + set_relationship + render action: :relationship + end + + def relationships + ids = params[:id].is_a?(Enumerable) ? params[:id].map { |id| id.to_i } : [params[:id].to_i] + @accounts = Account.find(ids) + @following = Account.following_map(ids, current_user.account_id) + @followed_by = Account.followed_by_map(ids, current_user.account_id) + @blocking = {} + end + + private + + def set_account + @account = Account.find(params[:id]) + end + + def set_relationship + @following = Account.following_map([@account.id], current_user.account_id) + @followed_by = Account.followed_by_map([@account.id], current_user.account_id) + @blocking = {} + end +end diff --git a/app/controllers/api/v1/apps_controller.rb b/app/controllers/api/v1/apps_controller.rb @@ -0,0 +1,13 @@ +class Api::V1::AppsController < ApplicationController + respond_to :json + + def create + @app = Doorkeeper::Application.create!(app_params) + end + + private + + def app_params + params.permit(:name, :redirect_uri) + end +end diff --git a/app/controllers/api/v1/follows_controller.rb b/app/controllers/api/v1/follows_controller.rb @@ -0,0 +1,13 @@ +class Api::V1::FollowsController < ApiController + before_action :doorkeeper_authorize! + respond_to :json + + def create + if params[:uri].blank? + raise ActiveRecord::RecordNotFound + end + + @account = FollowService.new.(current_user.account, params[:uri]).try(:target_account) + render action: :show + end +end diff --git a/app/controllers/api/v1/media_controller.rb b/app/controllers/api/v1/media_controller.rb @@ -0,0 +1,8 @@ +class Api::V1::MediaController < ApiController + before_action :doorkeeper_authorize! + respond_to :json + + def create + @media = MediaAttachment.create!(account: current_user.account, file: params[:file]) + end +end diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb @@ -0,0 +1,54 @@ +class Api::V1::StatusesController < ApiController + before_action :doorkeeper_authorize! + respond_to :json + + def show + @status = Status.find(params[:id]) + end + + def context + @status = Status.find(params[:id]) + @ancestors = @status.ancestors + @descendants = @status.descendants + end + + def create + @status = PostStatusService.new.(current_user.account, params[:status], params[:in_reply_to_id].blank? ? nil : Status.find(params[:in_reply_to_id]), params[:media_ids]) + render action: :show + end + + def destroy + @status = Status.where(account_id: current_user.account).find(params[:id]) + RemoveStatusService.new.(@status) + render_empty + end + + def reblog + @status = ReblogService.new.(current_user.account, Status.find(params[:id])).reload + render action: :show + end + + def unreblog + RemoveStatusService.new.(Status.where(account_id: current_user.account, reblog_of_id: params[:id]).first!) + @status = Status.find(params[:id]) + render action: :show + end + + def favourite + @status = FavouriteService.new.(current_user.account, Status.find(params[:id])).status.reload + render action: :show + end + + def unfavourite + @status = UnfavouriteService.new.(current_user.account, Status.find(params[:id])).status.reload + render action: :show + end + + def home + @statuses = Feed.new(:home, current_user.account).get(20, params[:max_id]).to_a + end + + def mentions + @statuses = Feed.new(:mentions, current_user.account).get(20, params[:max_id]).to_a + end +end diff --git a/app/helpers/api/accounts_helper.rb b/app/helpers/api/accounts_helper.rb @@ -1,2 +0,0 @@ -module Api::AccountsHelper -end diff --git a/app/helpers/api/apps_helper.rb b/app/helpers/api/apps_helper.rb @@ -1,2 +0,0 @@ -module Api::AppsHelper -end diff --git a/app/helpers/api/follows_helper.rb b/app/helpers/api/follows_helper.rb @@ -1,2 +0,0 @@ -module Api::FollowsHelper -end diff --git a/app/helpers/api/media_helper.rb b/app/helpers/api/media_helper.rb @@ -1,2 +0,0 @@ -module Api::MediaHelper -end diff --git a/app/helpers/api/salmon_helper.rb b/app/helpers/api/salmon_helper.rb @@ -1,2 +0,0 @@ -module Api::SalmonHelper -end diff --git a/app/helpers/api/statuses_helper.rb b/app/helpers/api/statuses_helper.rb @@ -1,2 +0,0 @@ -module Api::StatusesHelper -end diff --git a/app/helpers/api/subscriptions_helper.rb b/app/helpers/api/subscriptions_helper.rb @@ -1,2 +0,0 @@ -module Api::SubscriptionsHelper -end diff --git a/app/helpers/home_helper.rb b/app/helpers/home_helper.rb @@ -3,11 +3,11 @@ module HomeHelper { token: @token, - account: render(file: 'api/accounts/show', locals: { account: current_user.account }, formats: :json), + account: render(file: 'api/v1/accounts/show', locals: { account: current_user.account }, formats: :json), timelines: { - home: render(file: 'api/statuses/home', locals: { statuses: @home }, formats: :json), - mentions: render(file: 'api/statuses/mentions', locals: { statuses: @mentions }, formats: :json) + home: render(file: 'api/v1/statuses/home', locals: { statuses: @home }, formats: :json), + mentions: render(file: 'api/v1/statuses/mentions', locals: { statuses: @mentions }, formats: :json) } } end diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb @@ -54,6 +54,6 @@ class FeedManager end end - Rabl::Renderer.new('api/statuses/show', status, view_path: 'app/views', format: :json, scope: rabl_scope.new(target_account)).render + Rabl::Renderer.new('api/v1/statuses/show', status, view_path: 'app/views', format: :json, scope: rabl_scope.new(target_account)).render end end diff --git a/app/views/api/accounts/followers.rabl b/app/views/api/accounts/followers.rabl @@ -1,2 +0,0 @@ -collection @followers -extends('api/accounts/show') diff --git a/app/views/api/accounts/following.rabl b/app/views/api/accounts/following.rabl @@ -1,2 +0,0 @@ -collection @following -extends('api/accounts/show') diff --git a/app/views/api/accounts/relationships.rabl b/app/views/api/accounts/relationships.rabl @@ -1,2 +0,0 @@ -collection @accounts -extends 'api/accounts/relationship' diff --git a/app/views/api/accounts/statuses.rabl b/app/views/api/accounts/statuses.rabl @@ -1,2 +0,0 @@ -collection @statuses -extends('api/statuses/show') diff --git a/app/views/api/follows/show.rabl b/app/views/api/follows/show.rabl @@ -1,2 +0,0 @@ -object @account -extends('api/accounts/show') diff --git a/app/views/api/statuses/context.rabl b/app/views/api/statuses/context.rabl @@ -1,13 +0,0 @@ -object false - -node :ancestors do - @ancestors.map do |status| - partial('api/statuses/show', object: status) - end -end - -node :descendants do - @descendants.map do |status| - partial('api/statuses/show', object: status) - end -end diff --git a/app/views/api/statuses/home.rabl b/app/views/api/statuses/home.rabl @@ -1,2 +0,0 @@ -collection @statuses -extends('api/statuses/show') diff --git a/app/views/api/statuses/mentions.rabl b/app/views/api/statuses/mentions.rabl @@ -1,2 +0,0 @@ -collection @statuses -extends('api/statuses/show') diff --git a/app/views/api/statuses/show.rabl b/app/views/api/statuses/show.rabl @@ -1,31 +0,0 @@ -object @status -attributes :id, :created_at, :in_reply_to_id - -node(:uri) { |status| TagManager.instance.uri_for(status) } -node(:content) { |status| Formatter.instance.format(status) } -node(:url) { |status| TagManager.instance.url_for(status) } -node(:reblogs_count) { |status| status.reblogs_count } -node(:favourites_count) { |status| status.favourites_count } -node(:favourited) { |status| current_account.favourited?(status) } -node(:reblogged) { |status| current_account.reblogged?(status) } - -child :reblog => :reblog do - extends('api/statuses/show') -end - -child :account do - extends('api/accounts/show') -end - -child :media_attachments, object_root: false do - attributes :id, :remote_url, :type - - node(:url) { |media| full_asset_url(media.file.url) } - node(:preview_url) { |media| full_asset_url(media.file.url(:small)) } -end - -child :mentions, object_root: false do - node(:url) { |mention| TagManager.instance.url_for(mention.account) } - node(:acct) { |mention| mention.account.acct } - node(:id) { |mention| mention.account_id } -end diff --git a/app/views/api/v1/accounts/followers.rabl b/app/views/api/v1/accounts/followers.rabl @@ -0,0 +1,2 @@ +collection @followers +extends('api/v1/accounts/show') diff --git a/app/views/api/v1/accounts/following.rabl b/app/views/api/v1/accounts/following.rabl @@ -0,0 +1,2 @@ +collection @following +extends('api/v1/accounts/show') diff --git a/app/views/api/accounts/relationship.rabl b/app/views/api/v1/accounts/relationship.rabl diff --git a/app/views/api/v1/accounts/relationships.rabl b/app/views/api/v1/accounts/relationships.rabl @@ -0,0 +1,2 @@ +collection @accounts +extends 'api/v1/accounts/relationship' diff --git a/app/views/api/accounts/show.rabl b/app/views/api/v1/accounts/show.rabl diff --git a/app/views/api/v1/accounts/statuses.rabl b/app/views/api/v1/accounts/statuses.rabl @@ -0,0 +1,2 @@ +collection @statuses +extends('api/v1/statuses/show') diff --git a/app/views/api/apps/create.rabl b/app/views/api/v1/apps/create.rabl diff --git a/app/views/api/v1/follows/show.rabl b/app/views/api/v1/follows/show.rabl @@ -0,0 +1,2 @@ +object @account +extends('api/v1/accounts/show') diff --git a/app/views/api/media/create.rabl b/app/views/api/v1/media/create.rabl diff --git a/app/views/api/v1/statuses/context.rabl b/app/views/api/v1/statuses/context.rabl @@ -0,0 +1,13 @@ +object false + +node :ancestors do + @ancestors.map do |status| + partial('api/v1/statuses/show', object: status) + end +end + +node :descendants do + @descendants.map do |status| + partial('api/v1/statuses/show', object: status) + end +end diff --git a/app/views/api/v1/statuses/home.rabl b/app/views/api/v1/statuses/home.rabl @@ -0,0 +1,2 @@ +collection @statuses +extends('api/v1/statuses/show') diff --git a/app/views/api/v1/statuses/mentions.rabl b/app/views/api/v1/statuses/mentions.rabl @@ -0,0 +1,2 @@ +collection @statuses +extends('api/v1/statuses/show') diff --git a/app/views/api/v1/statuses/show.rabl b/app/views/api/v1/statuses/show.rabl @@ -0,0 +1,31 @@ +object @status +attributes :id, :created_at, :in_reply_to_id + +node(:uri) { |status| TagManager.instance.uri_for(status) } +node(:content) { |status| Formatter.instance.format(status) } +node(:url) { |status| TagManager.instance.url_for(status) } +node(:reblogs_count) { |status| status.reblogs_count } +node(:favourites_count) { |status| status.favourites_count } +node(:favourited) { |status| current_account.favourited?(status) } +node(:reblogged) { |status| current_account.reblogged?(status) } + +child :reblog => :reblog do + extends('api/v1/statuses/show') +end + +child :account do + extends('api/v1/accounts/show') +end + +child :media_attachments, object_root: false do + attributes :id, :remote_url, :type + + node(:url) { |media| full_asset_url(media.file.url) } + node(:preview_url) { |media| full_asset_url(media.file.url(:small)) } +end + +child :mentions, object_root: false do + node(:url) { |mention| TagManager.instance.url_for(mention.account) } + node(:acct) { |mention| mention.account.acct } + node(:id) { |mention| mention.account_id } +end diff --git a/config/routes.rb b/config/routes.rb @@ -39,38 +39,40 @@ Rails.application.routes.draw do post '/salmon/:id', to: 'salmon#update', as: :salmon # JSON / REST API - resources :statuses, only: [:create, :show, :destroy] do - collection do - get :home - get :mentions + namespace :v1 do + resources :statuses, only: [:create, :show, :destroy] do + collection do + get :home + get :mentions + end + + member do + get :context + + post :reblog + post :unreblog + post :favourite + post :unfavourite + end end - member do - get :context - - post :reblog - post :unreblog - post :favourite - post :unfavourite - end - end - - resources :follows, only: [:create] - resources :media, only: [:create] - resources :apps, only: [:create] - - resources :accounts, only: [:show] do - collection do - get :relationships - end - - member do - get :statuses - get :followers - get :following - - post :follow - post :unfollow + resources :follows, only: [:create] + resources :media, only: [:create] + resources :apps, only: [:create] + + resources :accounts, only: [:show] do + collection do + get :relationships + end + + member do + get :statuses + get :followers + get :following + + post :follow + post :unfollow + end end end end diff --git a/spec/controllers/api/accounts_controller_spec.rb b/spec/controllers/api/accounts_controller_spec.rb @@ -1,116 +0,0 @@ -require 'rails_helper' - -RSpec.describe Api::AccountsController, type: :controller do - render_views - - let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } - let(:token) { double acceptable?: true, resource_owner_id: user.id } - - before do - stub_request(:post, "https://pubsubhubbub.superfeedr.com/").to_return(:status => 200, :body => "", :headers => {}) - allow(controller).to receive(:doorkeeper_token) { token } - end - - describe 'GET #show' do - it 'returns http success' do - get :show, params: { id: user.account.id } - expect(response).to have_http_status(:success) - end - end - - describe 'GET #statuses' do - it 'returns http success' do - get :statuses, params: { id: user.account.id } - expect(response).to have_http_status(:success) - end - end - - describe 'GET #followers' do - it 'returns http success' do - get :followers, params: { id: user.account.id } - expect(response).to have_http_status(:success) - end - end - - describe 'GET #following' do - it 'returns http success' do - get :following, params: { id: user.account.id } - expect(response).to have_http_status(:success) - end - end - - describe 'POST #follow' do - let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account } - - before do - post :follow, params: { id: other_account.id } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - - it 'creates a following relation between user and target user' do - expect(user.account.following?(other_account)).to be true - end - end - - describe 'POST #unfollow' do - let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account } - - before do - user.account.follow!(other_account) - post :unfollow, params: { id: other_account.id } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - - it 'removes the following relation between user and target user' do - expect(user.account.following?(other_account)).to be false - end - end - - describe 'GET #relationships' do - let(:simon) { Fabricate(:user, email: 'simon@example.com', account: Fabricate(:account, username: 'simon')).account } - let(:lewis) { Fabricate(:user, email: 'lewis@example.com', account: Fabricate(:account, username: 'lewis')).account } - - before do - user.account.follow!(simon) - lewis.follow!(user.account) - end - - context 'provided only one ID' do - before do - get :relationships, params: { id: simon.id } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - - it 'returns JSON with correct data' do - json = body_as_json - - expect(json).to be_a Enumerable - expect(json.first[:following]).to be true - expect(json.first[:followed_by]).to be false - end - end - - context 'provided multiple IDs' do - before do - get :relationships, params: { id: [simon.id, lewis.id] } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - - xit 'returns JSON with correct data' do - # todo - end - end - end -end diff --git a/spec/controllers/api/apps_controller_spec.rb b/spec/controllers/api/apps_controller_spec.rb @@ -1,26 +0,0 @@ -require 'rails_helper' - -RSpec.describe Api::AppsController, type: :controller do - render_views - - describe 'POST #create' do - before do - post :create, params: { name: 'Test app', redirect_uri: 'urn:ietf:wg:oauth:2.0:oob' } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - - it 'creates an OAuth app' do - expect(Doorkeeper::Application.find_by(name: 'Test app')).to_not be nil - end - - it 'returns client ID and client secret' do - json = body_as_json - - expect(json[:client_id]).to_not be_blank - expect(json[:client_secret]).to_not be_blank - end - end -end diff --git a/spec/controllers/api/follows_controller_spec.rb b/spec/controllers/api/follows_controller_spec.rb @@ -1,50 +0,0 @@ -require 'rails_helper' - -RSpec.describe Api::FollowsController, type: :controller do - render_views - - let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } - let(:token) { double acceptable?: true, resource_owner_id: user.id } - - before do - allow(controller).to receive(:doorkeeper_token) { token } - end - - describe 'POST #create' do - before do - stub_request(:get, "https://quitter.no/.well-known/host-meta").to_return(request_fixture('.host-meta.txt')) - stub_request(:get, "https://quitter.no/.well-known/webfinger?resource=acct:gargron@quitter.no").to_return(request_fixture('webfinger.txt')) - stub_request(:get, "https://quitter.no/api/statuses/user_timeline/7477.atom").to_return(request_fixture('feed.txt')) - stub_request(:get, "https://quitter.no/avatar/7477-300-20160211190340.png").to_return(request_fixture('avatar.txt')) - stub_request(:post, "https://quitter.no/main/push/hub").to_return(:status => 200, :body => "", :headers => {}) - stub_request(:post, "https://quitter.no/main/salmon/user/7477").to_return(:status => 200, :body => "", :headers => {}) - stub_request(:post, "https://pubsubhubbub.superfeedr.com/").to_return(:status => 200, :body => "", :headers => {}) - - post :create, params: { uri: 'gargron@quitter.no' } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - - it 'creates account for remote user' do - expect(Account.find_by(username: 'gargron', domain: 'quitter.no')).to_not be_nil - end - - it 'creates a follow relation between user and remote user' do - expect(user.account.following?(Account.find_by(username: 'gargron', domain: 'quitter.no'))).to be true - end - - it 'sends a salmon slap to the remote user' do - expect(a_request(:post, "https://quitter.no/main/salmon/user/7477")).to have_been_made - end - - it 'notifies own hub' do - expect(a_request(:post, "https://pubsubhubbub.superfeedr.com/")).to have_been_made - end - - it 'subscribes to remote hub' do - expect(a_request(:post, "https://quitter.no/main/push/hub")).to have_been_made - end - end -end diff --git a/spec/controllers/api/media_controller_spec.rb b/spec/controllers/api/media_controller_spec.rb @@ -1,58 +0,0 @@ -require 'rails_helper' - -RSpec.describe Api::MediaController, type: :controller do - render_views - - let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } - let(:token) { double acceptable?: true, resource_owner_id: user.id } - - before do - allow(controller).to receive(:doorkeeper_token) { token } - end - - describe 'POST #create' do - context 'image/jpeg' do - before do - post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - - it 'creates a media attachment' do - expect(MediaAttachment.first).to_not be_nil - end - - it 'uploads a file' do - expect(MediaAttachment.first).to have_attached_file(:file) - end - - it 'returns media ID in JSON' do - expect(body_as_json[:id]).to eq MediaAttachment.first.id - end - end - - context 'video/webm' do - before do - post :create, params: { file: fixture_file_upload('files/attachment.webm', 'video/webm') } - end - - xit 'returns http success' do - expect(response).to have_http_status(:success) - end - - xit 'creates a media attachment' do - expect(MediaAttachment.first).to_not be_nil - end - - xit 'uploads a file' do - expect(MediaAttachment.first).to have_attached_file(:file) - end - - xit 'returns media ID in JSON' do - expect(body_as_json[:id]).to eq MediaAttachment.first.id - end - end - end -end diff --git a/spec/controllers/api/statuses_controller_spec.rb b/spec/controllers/api/statuses_controller_spec.rb @@ -1,173 +0,0 @@ -require 'rails_helper' - -RSpec.describe Api::StatusesController, type: :controller do - render_views - - let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } - let(:token) { double acceptable?: true, resource_owner_id: user.id } - - before do - stub_request(:post, "https://pubsubhubbub.superfeedr.com/").to_return(:status => 200, :body => "", :headers => {}) - allow(controller).to receive(:doorkeeper_token) { token } - end - - describe 'GET #show' do - let(:status) { Fabricate(:status, account: user.account) } - - it 'returns http success' do - get :show, params: { id: status.id } - expect(response).to have_http_status(:success) - end - end - - describe 'GET #context' do - let(:status) { Fabricate(:status, account: user.account) } - - before do - Fabricate(:status, account: user.account, thread: status) - end - - it 'returns http success' do - get :context, params: { id: status.id } - expect(response).to have_http_status(:success) - end - end - - describe 'GET #home' do - it 'returns http success' do - get :home - expect(response).to have_http_status(:success) - end - end - - describe 'GET #mentions' do - it 'returns http success' do - get :mentions - expect(response).to have_http_status(:success) - end - end - - describe 'POST #create' do - before do - post :create, params: { status: 'Hello world' } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - end - - describe 'DELETE #destroy' do - let(:status) { Fabricate(:status, account: user.account) } - - before do - post :destroy, params: { id: status.id } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - - it 'removes the status' do - expect(Status.find_by(id: status.id)).to be nil - end - end - - describe 'POST #reblog' do - let(:status) { Fabricate(:status, account: user.account) } - - before do - post :reblog, params: { id: status.id } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - - it 'updates the reblogs count' do - expect(status.reblogs_count).to eq 1 - end - - it 'updates the reblogged attribute' do - expect(user.account.reblogged?(status)).to be true - end - - it 'return json with updated attributes' do - hash_body = body_as_json - - expect(hash_body[:reblog][:id]).to eq status.id - expect(hash_body[:reblog][:reblogs_count]).to eq 1 - expect(hash_body[:reblog][:reblogged]).to be true - end - end - - describe 'POST #unreblog' do - let(:status) { Fabricate(:status, account: user.account) } - - before do - post :reblog, params: { id: status.id } - post :unreblog, params: { id: status.id } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - - it 'updates the reblogs count' do - expect(status.reblogs_count).to eq 0 - end - - it 'updates the reblogged attribute' do - expect(user.account.reblogged?(status)).to be false - end - end - - describe 'POST #favourite' do - let(:status) { Fabricate(:status, account: user.account) } - - before do - post :favourite, params: { id: status.id } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - - it 'updates the favourites count' do - expect(status.favourites_count).to eq 1 - end - - it 'updates the favourited attribute' do - expect(user.account.favourited?(status)).to be true - end - - it 'return json with updated attributes' do - hash_body = body_as_json - - expect(hash_body[:id]).to eq status.id - expect(hash_body[:favourites_count]).to eq 1 - expect(hash_body[:favourited]).to be true - end - end - - describe 'POST #unfavourite' do - let(:status) { Fabricate(:status, account: user.account) } - - before do - post :favourite, params: { id: status.id } - post :unfavourite, params: { id: status.id } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - - it 'updates the favourites count' do - expect(status.favourites_count).to eq 0 - end - - it 'updates the favourited attribute' do - expect(user.account.favourited?(status)).to be false - end - end -end diff --git a/spec/controllers/api/v1/accounts_controller_spec.rb b/spec/controllers/api/v1/accounts_controller_spec.rb @@ -0,0 +1,116 @@ +require 'rails_helper' + +RSpec.describe Api::V1::AccountsController, type: :controller do + render_views + + let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } + let(:token) { double acceptable?: true, resource_owner_id: user.id } + + before do + stub_request(:post, "https://pubsubhubbub.superfeedr.com/").to_return(:status => 200, :body => "", :headers => {}) + allow(controller).to receive(:doorkeeper_token) { token } + end + + describe 'GET #show' do + it 'returns http success' do + get :show, params: { id: user.account.id } + expect(response).to have_http_status(:success) + end + end + + describe 'GET #statuses' do + it 'returns http success' do + get :statuses, params: { id: user.account.id } + expect(response).to have_http_status(:success) + end + end + + describe 'GET #followers' do + it 'returns http success' do + get :followers, params: { id: user.account.id } + expect(response).to have_http_status(:success) + end + end + + describe 'GET #following' do + it 'returns http success' do + get :following, params: { id: user.account.id } + expect(response).to have_http_status(:success) + end + end + + describe 'POST #follow' do + let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account } + + before do + post :follow, params: { id: other_account.id } + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + it 'creates a following relation between user and target user' do + expect(user.account.following?(other_account)).to be true + end + end + + describe 'POST #unfollow' do + let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account } + + before do + user.account.follow!(other_account) + post :unfollow, params: { id: other_account.id } + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + it 'removes the following relation between user and target user' do + expect(user.account.following?(other_account)).to be false + end + end + + describe 'GET #relationships' do + let(:simon) { Fabricate(:user, email: 'simon@example.com', account: Fabricate(:account, username: 'simon')).account } + let(:lewis) { Fabricate(:user, email: 'lewis@example.com', account: Fabricate(:account, username: 'lewis')).account } + + before do + user.account.follow!(simon) + lewis.follow!(user.account) + end + + context 'provided only one ID' do + before do + get :relationships, params: { id: simon.id } + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + it 'returns JSON with correct data' do + json = body_as_json + + expect(json).to be_a Enumerable + expect(json.first[:following]).to be true + expect(json.first[:followed_by]).to be false + end + end + + context 'provided multiple IDs' do + before do + get :relationships, params: { id: [simon.id, lewis.id] } + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + xit 'returns JSON with correct data' do + # todo + end + end + end +end diff --git a/spec/controllers/api/v1/apps_controller_spec.rb b/spec/controllers/api/v1/apps_controller_spec.rb @@ -0,0 +1,26 @@ +require 'rails_helper' + +RSpec.describe Api::V1::AppsController, type: :controller do + render_views + + describe 'POST #create' do + before do + post :create, params: { name: 'Test app', redirect_uri: 'urn:ietf:wg:oauth:2.0:oob' } + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + it 'creates an OAuth app' do + expect(Doorkeeper::Application.find_by(name: 'Test app')).to_not be nil + end + + it 'returns client ID and client secret' do + json = body_as_json + + expect(json[:client_id]).to_not be_blank + expect(json[:client_secret]).to_not be_blank + end + end +end diff --git a/spec/controllers/api/v1/follows_controller_spec.rb b/spec/controllers/api/v1/follows_controller_spec.rb @@ -0,0 +1,50 @@ +require 'rails_helper' + +RSpec.describe Api::V1::FollowsController, type: :controller do + render_views + + let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } + let(:token) { double acceptable?: true, resource_owner_id: user.id } + + before do + allow(controller).to receive(:doorkeeper_token) { token } + end + + describe 'POST #create' do + before do + stub_request(:get, "https://quitter.no/.well-known/host-meta").to_return(request_fixture('.host-meta.txt')) + stub_request(:get, "https://quitter.no/.well-known/webfinger?resource=acct:gargron@quitter.no").to_return(request_fixture('webfinger.txt')) + stub_request(:get, "https://quitter.no/api/statuses/user_timeline/7477.atom").to_return(request_fixture('feed.txt')) + stub_request(:get, "https://quitter.no/avatar/7477-300-20160211190340.png").to_return(request_fixture('avatar.txt')) + stub_request(:post, "https://quitter.no/main/push/hub").to_return(:status => 200, :body => "", :headers => {}) + stub_request(:post, "https://quitter.no/main/salmon/user/7477").to_return(:status => 200, :body => "", :headers => {}) + stub_request(:post, "https://pubsubhubbub.superfeedr.com/").to_return(:status => 200, :body => "", :headers => {}) + + post :create, params: { uri: 'gargron@quitter.no' } + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + it 'creates account for remote user' do + expect(Account.find_by(username: 'gargron', domain: 'quitter.no')).to_not be_nil + end + + it 'creates a follow relation between user and remote user' do + expect(user.account.following?(Account.find_by(username: 'gargron', domain: 'quitter.no'))).to be true + end + + it 'sends a salmon slap to the remote user' do + expect(a_request(:post, "https://quitter.no/main/salmon/user/7477")).to have_been_made + end + + it 'notifies own hub' do + expect(a_request(:post, "https://pubsubhubbub.superfeedr.com/")).to have_been_made + end + + it 'subscribes to remote hub' do + expect(a_request(:post, "https://quitter.no/main/push/hub")).to have_been_made + end + end +end diff --git a/spec/controllers/api/v1/media_controller_spec.rb b/spec/controllers/api/v1/media_controller_spec.rb @@ -0,0 +1,58 @@ +require 'rails_helper' + +RSpec.describe Api::V1::MediaController, type: :controller do + render_views + + let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } + let(:token) { double acceptable?: true, resource_owner_id: user.id } + + before do + allow(controller).to receive(:doorkeeper_token) { token } + end + + describe 'POST #create' do + context 'image/jpeg' do + before do + post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') } + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + it 'creates a media attachment' do + expect(MediaAttachment.first).to_not be_nil + end + + it 'uploads a file' do + expect(MediaAttachment.first).to have_attached_file(:file) + end + + it 'returns media ID in JSON' do + expect(body_as_json[:id]).to eq MediaAttachment.first.id + end + end + + context 'video/webm' do + before do + post :create, params: { file: fixture_file_upload('files/attachment.webm', 'video/webm') } + end + + xit 'returns http success' do + expect(response).to have_http_status(:success) + end + + xit 'creates a media attachment' do + expect(MediaAttachment.first).to_not be_nil + end + + xit 'uploads a file' do + expect(MediaAttachment.first).to have_attached_file(:file) + end + + xit 'returns media ID in JSON' do + expect(body_as_json[:id]).to eq MediaAttachment.first.id + end + end + end +end diff --git a/spec/controllers/api/v1/statuses_controller_spec.rb b/spec/controllers/api/v1/statuses_controller_spec.rb @@ -0,0 +1,173 @@ +require 'rails_helper' + +RSpec.describe Api::V1::StatusesController, type: :controller do + render_views + + let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } + let(:token) { double acceptable?: true, resource_owner_id: user.id } + + before do + stub_request(:post, "https://pubsubhubbub.superfeedr.com/").to_return(:status => 200, :body => "", :headers => {}) + allow(controller).to receive(:doorkeeper_token) { token } + end + + describe 'GET #show' do + let(:status) { Fabricate(:status, account: user.account) } + + it 'returns http success' do + get :show, params: { id: status.id } + expect(response).to have_http_status(:success) + end + end + + describe 'GET #context' do + let(:status) { Fabricate(:status, account: user.account) } + + before do + Fabricate(:status, account: user.account, thread: status) + end + + it 'returns http success' do + get :context, params: { id: status.id } + expect(response).to have_http_status(:success) + end + end + + describe 'GET #home' do + it 'returns http success' do + get :home + expect(response).to have_http_status(:success) + end + end + + describe 'GET #mentions' do + it 'returns http success' do + get :mentions + expect(response).to have_http_status(:success) + end + end + + describe 'POST #create' do + before do + post :create, params: { status: 'Hello world' } + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + end + + describe 'DELETE #destroy' do + let(:status) { Fabricate(:status, account: user.account) } + + before do + post :destroy, params: { id: status.id } + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + it 'removes the status' do + expect(Status.find_by(id: status.id)).to be nil + end + end + + describe 'POST #reblog' do + let(:status) { Fabricate(:status, account: user.account) } + + before do + post :reblog, params: { id: status.id } + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + it 'updates the reblogs count' do + expect(status.reblogs_count).to eq 1 + end + + it 'updates the reblogged attribute' do + expect(user.account.reblogged?(status)).to be true + end + + it 'return json with updated attributes' do + hash_body = body_as_json + + expect(hash_body[:reblog][:id]).to eq status.id + expect(hash_body[:reblog][:reblogs_count]).to eq 1 + expect(hash_body[:reblog][:reblogged]).to be true + end + end + + describe 'POST #unreblog' do + let(:status) { Fabricate(:status, account: user.account) } + + before do + post :reblog, params: { id: status.id } + post :unreblog, params: { id: status.id } + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + it 'updates the reblogs count' do + expect(status.reblogs_count).to eq 0 + end + + it 'updates the reblogged attribute' do + expect(user.account.reblogged?(status)).to be false + end + end + + describe 'POST #favourite' do + let(:status) { Fabricate(:status, account: user.account) } + + before do + post :favourite, params: { id: status.id } + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + it 'updates the favourites count' do + expect(status.favourites_count).to eq 1 + end + + it 'updates the favourited attribute' do + expect(user.account.favourited?(status)).to be true + end + + it 'return json with updated attributes' do + hash_body = body_as_json + + expect(hash_body[:id]).to eq status.id + expect(hash_body[:favourites_count]).to eq 1 + expect(hash_body[:favourited]).to be true + end + end + + describe 'POST #unfavourite' do + let(:status) { Fabricate(:status, account: user.account) } + + before do + post :favourite, params: { id: status.id } + post :unfavourite, params: { id: status.id } + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + it 'updates the favourites count' do + expect(status.favourites_count).to eq 0 + end + + it 'updates the favourited attribute' do + expect(user.account.favourited?(status)).to be false + end + end +end diff --git a/spec/helpers/api/accounts_helper_spec.rb b/spec/helpers/api/accounts_helper_spec.rb @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe Api::AccountsHelper, type: :helper do - -end diff --git a/spec/helpers/api/apps_helper_spec.rb b/spec/helpers/api/apps_helper_spec.rb @@ -1,15 +0,0 @@ -require 'rails_helper' - -# Specs in this file have access to a helper object that includes -# the Api::AppsHelper. For example: -# -# describe Api::AppsHelper do -# describe "string concat" do -# it "concats two strings with spaces" do -# expect(helper.concat_strings("this","that")).to eq("this that") -# end -# end -# end -RSpec.describe Api::AppsHelper, type: :helper do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/helpers/api/follows_helper_spec.rb b/spec/helpers/api/follows_helper_spec.rb @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe Api::FollowsHelper, type: :helper do - -end diff --git a/spec/helpers/api/media_helper_spec.rb b/spec/helpers/api/media_helper_spec.rb @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe Api::MediaHelper, type: :helper do - -end diff --git a/spec/helpers/api/salmon_helper_spec.rb b/spec/helpers/api/salmon_helper_spec.rb @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe Api::SalmonHelper, type: :helper do - -end diff --git a/spec/helpers/api/statuses_helper_spec.rb b/spec/helpers/api/statuses_helper_spec.rb @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe Api::StatusesHelper, type: :helper do - -end diff --git a/spec/helpers/api/subscriptions_helper_spec.rb b/spec/helpers/api/subscriptions_helper_spec.rb @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe Api::SubscriptionsHelper, type: :helper do - -end