Aspects API Endpoint complete with full tests
This commit is contained in:
parent
173461ac3d
commit
db7fe69ce4
6 changed files with 414 additions and 4 deletions
72
app/controllers/api/v1/aspects_controller.rb
Normal file
72
app/controllers/api/v1/aspects_controller.rb
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V1
|
||||
class AspectsController < Api::V1::BaseController
|
||||
before_action only: %i[index show] do
|
||||
require_access_token %w[read]
|
||||
end
|
||||
|
||||
before_action only: %i[create update destroy] do
|
||||
require_access_token %w[read write]
|
||||
end
|
||||
|
||||
def index
|
||||
aspects = current_user.aspects.map {|a| AspectPresenter.new(a).as_api_json(false) }
|
||||
render json: aspects
|
||||
end
|
||||
|
||||
def show
|
||||
aspect = current_user.aspects.where(id: params[:id]).first
|
||||
if aspect
|
||||
render json: AspectPresenter.new(aspect).as_api_json(true)
|
||||
else
|
||||
render json: I18n.t("api.endpoint_errors.aspects.not_found"), status: :not_found
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
params.require(%i[name chat_enabled])
|
||||
aspect = current_user.aspects.build(name: params[:name], chat_enabled: params[:chat_enabled])
|
||||
if aspect&.save
|
||||
render json: AspectPresenter.new(aspect).as_api_json(true)
|
||||
else
|
||||
render json: I18n.t("api.endpoint_errors.aspects.cant_create"), status: :unprocessable_entity
|
||||
end
|
||||
rescue ActionController::ParameterMissing
|
||||
render json: I18n.t("api.endpoint_errors.aspects.cant_create"), status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def update
|
||||
aspect = current_user.aspects.where(id: params[:id]).first
|
||||
|
||||
if !aspect
|
||||
render json: I18n.t("api.endpoint_errors.aspects.cant_update"), status: :not_found
|
||||
elsif aspect.update!(aspect_params(true))
|
||||
render json: AspectPresenter.new(aspect).as_api_json(true)
|
||||
else
|
||||
render json: I18n.t("api.endpoint_errors.aspects.cant_update"), status: :unprocessable_entity
|
||||
end
|
||||
rescue ActionController::ParameterMissing, ActiveRecord::RecordInvalid
|
||||
render json: I18n.t("api.endpoint_errors.aspects.cant_update"), status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def destroy
|
||||
aspect = current_user.aspects.where(id: params[:id]).first
|
||||
if aspect&.destroy
|
||||
head :no_content
|
||||
else
|
||||
render json: I18n.t("api.endpoint_errors.aspects.cant_delete"), status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def aspect_params(allow_order=false)
|
||||
parameters = params.permit(:name, :chat_enabled)
|
||||
parameters[:order_id] = params[:order] if params.has_key?(:order) && allow_order
|
||||
parameters
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -11,7 +11,18 @@ class AspectPresenter < BasePresenter
|
|||
}
|
||||
end
|
||||
|
||||
def to_json(options = {})
|
||||
def as_api_json(full=false)
|
||||
values = {
|
||||
id: @aspect.id,
|
||||
name: @aspect.name,
|
||||
order: @aspect.order_id
|
||||
}
|
||||
|
||||
values[:chat_enabled] = @aspect.chat_enabled if full
|
||||
values
|
||||
end
|
||||
|
||||
def to_json(options={})
|
||||
as_json.to_json(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -951,6 +951,11 @@ en:
|
|||
login_required: "You must first login before you can authorize this application"
|
||||
could_not_authorize: "The application could not be authorized"
|
||||
endpoint_errors:
|
||||
aspects:
|
||||
cant_create: "Failed to create the aspect"
|
||||
cant_delete: "Failed to delete the aspect"
|
||||
cant_update: "Failed to update the aspect"
|
||||
not_found: "Aspect with provided ID could not be found"
|
||||
conversations:
|
||||
not_found: "Conversation with provided guid could not be found"
|
||||
cant_process: "Couldn’t accept or process the conversation"
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ Rails.application.routes.draw do
|
|||
get "podmin", to: "home#podmin"
|
||||
|
||||
api_version(module: "Api::V1", path: {value: "api/v1"}) do
|
||||
resources :aspects, only: %i[show index create destroy update]
|
||||
resources :posts, only: %i[show create destroy] do
|
||||
resources :comments, only: %i[create index destroy] do
|
||||
post "report" => "comments#report"
|
||||
|
|
@ -232,6 +233,7 @@ Rails.application.routes.draw do
|
|||
resources :conversations, only: %i[show index create destroy] do
|
||||
resources :messages, only: %i[index create]
|
||||
end
|
||||
|
||||
get "streams/activity" => "streams#activity", :as => "activity_stream"
|
||||
get "streams/main" => "streams#multi", :as => "stream"
|
||||
get "streams/tags" => "streams#followed_tags", :as => "followed_tags_stream"
|
||||
|
|
|
|||
302
spec/integration/api/aspects_controller_spec.rb
Normal file
302
spec/integration/api/aspects_controller_spec.rb
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
# frozen_sTring_literal: true
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
describe Api::V1::AspectsController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth_read_only) { FactoryGirl.create(:auth_with_read) }
|
||||
let!(:access_token) { auth.create_access_token.to_s }
|
||||
let!(:access_token_read_only) { auth_read_only.create_access_token.to_s }
|
||||
|
||||
before do
|
||||
@aspect1 = auth.user.aspects.where(name: "generic").first
|
||||
@aspect2 = auth.user.aspects.create(name: "another aspect")
|
||||
end
|
||||
|
||||
describe "#index" do
|
||||
it "returns list of aspects" do
|
||||
get(
|
||||
api_v1_aspects_path,
|
||||
params: {access_token: access_token}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
aspects = JSON.parse(response.body)
|
||||
expect(aspects.length).to eq(auth.user.aspects.length)
|
||||
aspects.each do |aspect|
|
||||
found_aspect = auth.user.aspects.find_by(id: aspect["id"])
|
||||
expect(aspect["name"]).to eq(found_aspect.name)
|
||||
expect(aspect["order"]).to eq(found_aspect.order_id)
|
||||
end
|
||||
end
|
||||
|
||||
it "fails if invalid token" do
|
||||
get(
|
||||
api_v1_aspects_path,
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#show" do
|
||||
context "with correct id" do
|
||||
it "returns aspect" do
|
||||
get(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {access_token: access_token}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
aspect = JSON.parse(response.body)
|
||||
expect(aspect["id"]).to eq(@aspect2.id)
|
||||
expect(aspect["name"]).to eq(@aspect2.name)
|
||||
expect(aspect["order"]).to eq(@aspect2.order_id)
|
||||
expect(aspect["chat_enabled"]).to eq(@aspect2.chat_enabled)
|
||||
end
|
||||
end
|
||||
|
||||
context "with incorrect id" do
|
||||
it "fails to return with error" do
|
||||
get(
|
||||
api_v1_aspect_path("-1"),
|
||||
params: {access_token: access_token}
|
||||
)
|
||||
expect(response.status).to eq(404)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.aspects.not_found"))
|
||||
end
|
||||
end
|
||||
|
||||
context "when not logged in" do
|
||||
it "fails to return with error" do
|
||||
get(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#create" do
|
||||
context "with full aspect settings" do
|
||||
it "creates aspect" do
|
||||
new_name = "diaspora developers"
|
||||
post(
|
||||
api_v1_aspects_path,
|
||||
params: {name: new_name, chat_enabled: true, access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
aspect = JSON.parse(response.body)
|
||||
expect(aspect["name"]).to eq(new_name)
|
||||
expect(aspect["chat_enabled"]).to be_truthy
|
||||
expect(aspect.has_key?("id")).to be_truthy
|
||||
expect(aspect.has_key?("order")).to be_truthy
|
||||
end
|
||||
|
||||
it "fails to create duplicate aspect" do
|
||||
post(
|
||||
api_v1_aspects_path,
|
||||
params: {name: @aspect1.name, chat_enabled: true, access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(422)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.aspects.cant_create"))
|
||||
end
|
||||
end
|
||||
|
||||
context "with malformed settings" do
|
||||
it "fails when missing name" do
|
||||
post(
|
||||
api_v1_aspects_path,
|
||||
params: {chat_enabled: true, access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(422)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.aspects.cant_create"))
|
||||
end
|
||||
|
||||
it "fails when missing chat" do
|
||||
post(
|
||||
api_v1_aspects_path,
|
||||
params: {name: "new_aspect", access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(422)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.aspects.cant_create"))
|
||||
end
|
||||
end
|
||||
|
||||
context "improper credentials" do
|
||||
it "fails when not logged in" do
|
||||
post(
|
||||
api_v1_aspects_path,
|
||||
params: {name: "new_name", chat_enabled: true, access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
|
||||
it "fails when logged in read only" do
|
||||
post(
|
||||
api_v1_aspects_path,
|
||||
params: {name: "new_name", chat_enabled: true, access_token: access_token_read_only}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#update" do
|
||||
context "with aspect settings" do
|
||||
it "updates full aspect" do
|
||||
new_name = "NewAspectName"
|
||||
new_chat = @aspect2.chat_enabled
|
||||
order = @aspect2.order_id + 1
|
||||
patch(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {name: new_name, chat_enabled: new_chat, order: order, access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
aspect = JSON.parse(response.body)
|
||||
expect(aspect["name"]).to eq(new_name)
|
||||
expect(aspect["chat_enabled"]).to eq(new_chat)
|
||||
expect(aspect["order"]).to eq(order)
|
||||
expect(aspect["id"]).to eq(@aspect2.id)
|
||||
end
|
||||
|
||||
it "updates name only aspect" do
|
||||
new_name = "NewAspectName"
|
||||
patch(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {name: new_name, access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
aspect = JSON.parse(response.body)
|
||||
expect(aspect["name"]).to eq(new_name)
|
||||
expect(aspect["id"]).to eq(@aspect2.id)
|
||||
end
|
||||
|
||||
it "updates chat only" do
|
||||
new_chat = @aspect2.chat_enabled
|
||||
patch(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {chat_enabled: new_chat, access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
aspect = JSON.parse(response.body)
|
||||
expect(aspect["chat_enabled"]).to eq(new_chat)
|
||||
expect(aspect["id"]).to eq(@aspect2.id)
|
||||
end
|
||||
|
||||
it "updates order only" do
|
||||
order = @aspect2.order_id + 1
|
||||
patch(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {order: order, access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
aspect = JSON.parse(response.body)
|
||||
expect(aspect["order"]).to eq(order)
|
||||
expect(aspect["id"]).to eq(@aspect2.id)
|
||||
end
|
||||
|
||||
it "succeds with no arguments" do
|
||||
patch(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
aspect = JSON.parse(response.body)
|
||||
expect(aspect["name"]).to eq(@aspect2.name)
|
||||
expect(aspect["chat_enabled"]).to eq(@aspect2.chat_enabled)
|
||||
expect(aspect["id"]).to eq(@aspect2.id)
|
||||
end
|
||||
end
|
||||
|
||||
context "with bad parameters" do
|
||||
it "fails with reused name" do
|
||||
patch(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {name: @aspect1.name, access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(422)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.aspects.cant_update"))
|
||||
end
|
||||
|
||||
it "fails with bad id" do
|
||||
patch(
|
||||
api_v1_aspect_path("-1"),
|
||||
params: {name: "NewAspectName", access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.aspects.cant_update"))
|
||||
end
|
||||
end
|
||||
|
||||
context "improper credentials" do
|
||||
it "fails when not logged in" do
|
||||
patch(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
|
||||
it "fails when logged in read only" do
|
||||
patch(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#delete" do
|
||||
context "with correct ID" do
|
||||
it "deletes aspect" do
|
||||
delete(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {access_token: access_token}
|
||||
)
|
||||
expect(response.status).to eq(204)
|
||||
end
|
||||
end
|
||||
|
||||
context "with bad ID" do
|
||||
it "fails to delete with error" do
|
||||
delete(
|
||||
api_v1_aspect_path("-1"),
|
||||
params: {access_token: access_token}
|
||||
)
|
||||
expect(response.status).to eq(422)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.aspects.cant_delete"))
|
||||
end
|
||||
end
|
||||
|
||||
context "improper credentials" do
|
||||
it "fails when not logged in" do
|
||||
delete(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
|
||||
it "fails when logged in read only" do
|
||||
delete(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
describe AspectPresenter do
|
||||
before do
|
||||
@presenter = AspectPresenter.new(bob.aspects.first)
|
||||
@aspect = bob.aspects.first
|
||||
@presenter = AspectPresenter.new(@aspect)
|
||||
end
|
||||
|
||||
describe '#to_json' do
|
||||
|
|
@ -10,4 +11,21 @@ describe AspectPresenter do
|
|||
expect(@presenter.to_json).to be_present
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#to_api_json" do
|
||||
it "creates simple JSON" do
|
||||
aspect_json = @presenter.as_api_json(false)
|
||||
expect(aspect_json[:id]).to eq(@aspect.id)
|
||||
expect(aspect_json[:name]).to eq(@aspect.name)
|
||||
expect(aspect_json[:order]).to eq(@aspect.order_id)
|
||||
end
|
||||
|
||||
it "produces full JSON" do
|
||||
aspect_json = @presenter.as_api_json(true)
|
||||
expect(aspect_json[:id]).to eq(@aspect.id)
|
||||
expect(aspect_json[:name]).to eq(@aspect.name)
|
||||
expect(aspect_json[:order]).to eq(@aspect.order_id)
|
||||
expect(aspect_json[:chat_enabled]).to eq(@aspect.chat_enabled)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue