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:
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