VRFS-82 more band invitation development / unit test enhancements

This commit is contained in:
Brian Smith 2012-11-25 14:38:24 -05:00
parent 5197f85219
commit 05cb87c35a
16 changed files with 360 additions and 120 deletions

View File

@ -1,7 +1,6 @@
class ApiBandsController < ApplicationController
class ApiBandsController < ApiController
before_filter :api_signed_in_user, :only => [:index, :show, :create, :update,
:following_create, :following_destroy]
before_filter :api_signed_in_user, :except => [:index, :show, :follower_index]
respond_to :json
@ -21,23 +20,16 @@ class ApiBandsController < ApplicationController
params[:city],
params[:state],
params[:country],
params[:genres])
params[:genres],
current_user.id)
respond_with @band, responder: ApiResponder, :location => api_band_detail_url(@band)
=begin
# check for errors
if @band.errors.nil? || @band.errors.size == 0
respond_with @band, responder: ApiResponder, :location => api_band_detail_url(@band)
else
raise ActiveRecord::Rollback
response.status = :unprocessable_entity
respond_with @band
end
=end
respond_with @band, responder: ApiResponder, :status => 201, :location => api_band_detail_url(@band)
end
def update
@band = Band.find_by_id(params[:id])
auth_band_member(@band, current_user)
@band = Band.save(params[:id],
params[:name],
params[:website],
@ -45,17 +37,10 @@ class ApiBandsController < ApplicationController
params[:city],
params[:state],
params[:country],
params[:genres])
params[:genres],
current_user.id,)
# check for errors
if @band.errors.nil? || @band.errors.size == 0
respond_with @band, responder: ApiResponder, :status => :ok
else
raise ActiveRecord::Rollback
response.status = :unprocessable_entity
respond_with @band
end
respond_with @band, responder: ApiResponder, :status => :ok
end
###################### FOLLOWERS ########################
@ -66,13 +51,11 @@ class ApiBandsController < ApplicationController
###################### RECORDINGS #######################
def recording_index
hide_private = false
band = Band.find(params[:id])
@band = Band.find(params[:id])
# hide private Recordings from anyone who's not in the Band
unless band.users.exists? current_user
unless @band.users.exists? current_user
hide_private = true
end
@ -80,7 +63,7 @@ class ApiBandsController < ApplicationController
@recordings = Recording.find(:all,
:joins => :musician_recordings,
:select => "recordings.id, recordings.description, recordings.public",
:conditions => ["bands_recordings.band_id='#{params[:id]}'' AND public=true"])
:conditions => ["bands_recordings.band_id='#{params[:id]}' AND public=true"])
#.paginate(page: params[:page])
else
@ -89,11 +72,12 @@ class ApiBandsController < ApplicationController
:select => "recordings.id, recordings.description, recordings.public",
:conditions => ["bands_recordings.band_id='#{params[:id]}'"])
end
respond_with @recordings, responder: ApiResponder, :status => 200
end
def recording_show
hide_private = false
band = Band.find(params[:id])
# hide private Recordings from anyone who's not in the Band
@ -111,6 +95,9 @@ class ApiBandsController < ApplicationController
end
def recording_create
@band = Band.find_by_id(params[:id])
auth_band_member(@band, current_user)
@recording = Recording.save(params[:recording_id],
params[:public],
params[:description],
@ -118,36 +105,102 @@ class ApiBandsController < ApplicationController
params[:id],
true)
if @recording.errors.nil? || @recording.errors.size == 0
@band = Band.find(params[:id])
respond_with @recording, responder: ApiResponder, :status => 201, :location => api_band_recording_detail_url(@band, @recording)
else
raise ActiveRecord::Rollback
response.status = :unprocessable_entity
respond_with @recording
end
respond_with @recording, responder: ApiResponder, :status => 201, :location => api_band_recording_detail_url(@band, @recording)
end
def recording_update
@recording = Recording.save(params[:recording_id],
params[:public],
params[:description],
current_user.id,
params[:id],
false)
respond_with @recording, responder: ApiResponder, :status => 200
end
def recording_destroy
# TODO: ensure current_user is band member
@band = Band.find_by_id(params[:id])
auth_band_member(@band, current_user)
@recording = Recording.find(params[:recording_id])
@recording.delete
respond_with responder: ApiResponder, :status => 204
unless @recording.nil?
@recording.delete
respond_with responder: ApiResponder, :status => 204
end
# no recording was found with this ID
render :json => { :message => ValidationMessages::RECORDING_NOT_FOUND }, :status => 404
end
###################### INVITATIONS ######################
def invitation_index
# verify current_user is member of Band
@band = Band.find_by_id(params[:id])
auth_band_member(@band, current_user)
@invitations = @band.invitations #BandInvitation.find_by_band_id(params[:id])
respond_with @invitations, responder: ApiResponder, :status => 200
end
unless @band.users.exists? current_user
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
@invitations = BandInvitation.find_by_band_id(@band.id)
def invitation_show
@band = Band.find_by_id(params[:id])
auth_band_member(@band, current_user)
@invitation = BandInvitation.find(params[:invitation_id])
end
def invitation_create
@band = Band.find_by_id(params[:id])
auth_band_member(@band, current_user)
@invitation = BandInvitation.save(params[:invitation_id],
params[:id],
params[:user_id],
current_user.id,
params[:accepted])
respond_with @invitation, responder: ApiResponder, :status => 201, :location => api_band_invitation_detail_url(@band, @invitation)
end
=begin
def invitation_update
@user = current_user
invitation = @user.received_band_invitations.find_by_band_id(params[:id])
unless invitation.nil?
@invitation = BandInvitation.save(params[:recording_id],
params[:id],
current_user.id,
current_user.id,
params[:accepted])
respond_with @invitation, responder: ApiResponder, :status => 200
end
# no invitation was found for this user and band
render :json => { :message => ValidationMessages::BAND_INVITATION_NOT_FOUND }, :status => 404
end
=end
def invitation_destroy
@band = Band.find_by_id(params[:id])
auth_band_member(@band, current_user)
@invitation = BandInvitation.find(params[:invitation_id])
unless @invitation.nil?
@invitation.delete
respond_with responder: ApiResponder, :status => 204
end
render :json => { :message => ValidationMessages::BAND_INVITATION_NOT_FOUND }, :status => 404
end
#############################################################################
protected
# ensures user is a member of the band
def auth_band_member(band, user)
unless band.users.exists? user
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
end
end

View File

@ -5,7 +5,7 @@ class ApiController < ApplicationController
# define common error handlers
rescue_from 'JamRuby::StateError' do |exception|
@exception = exception
render "errors/state_error.rabl", :status => 400
render "errors/state_error", :status => 400
end
rescue_from 'JamRuby::JamArgumentError' do |exception|
@exception = exception
@ -30,8 +30,7 @@ class ApiController < ApplicationController
protected
def auth_user(id)
if current_user.id != id
#respond_with "You do not have permissions to perform this action.", responder: ApiResponder, :status => 403
unless current_user.id == id
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
end

View File

@ -70,20 +70,12 @@ class ApiUsersController < ApiController
params[:country],
params[:instruments])
# check for errors
if @user.errors.nil? || @user.errors.size == 0
respond_with @user, responder: ApiResponder, :status => :ok
else
raise ActiveRecord::Rollback
response.status = :unprocessable_entity
respond_with @user
end
respond_with @user, responder: ApiResponder, :status => :ok
end
def delete
@user = User.find(params[:id])
@user.destroy # required to make 'tire' integration work
auth_user @user.destroy # required to make 'tire' integration work
respond_with responder: ApiResponder, :status => 204
end
@ -146,6 +138,8 @@ class ApiUsersController < ApiController
:select => "recordings.id, recordings.description, recordings.public",
:conditions => ["musicians_recordings.user_id='#{params[:id]}'"])
end
respond_with @recordings, responder: ApiResponder, :status => 200
end
def recording_show
@ -173,15 +167,8 @@ class ApiUsersController < ApiController
params[:id],
false)
# check for errors
if @recording.errors.nil? || @recording.errors.size == 0
@user = current_user
respond_with @recording, responder: ApiResponder, :status => 201, :location => api_recording_detail_url(@user, @recording)
else
raise ActiveRecord::Rollback
response.status = :unprocessable_entity
respond_with @recording
end
@user = current_user
respond_with @recording, responder: ApiResponder, :status => 201, :location => api_recording_detail_url(@user, @recording)
end
def recording_update
@ -192,15 +179,7 @@ class ApiUsersController < ApiController
params[:id],
false)
# check for errors
if @recording.errors.nil? || @recording.errors.size == 0
respond_with @recording, responder: ApiResponder, :status => 200
else
raise ActiveRecord::Rollback
response.status = :unprocessable_entity
respond_with @recording
end
respond_with @recording, responder: ApiResponder, :status => 200
end
def recording_destroy
@ -208,7 +187,6 @@ class ApiUsersController < ApiController
@recording = Recording.find(params[:recording_id])
@recording.delete
respond_with responder: ApiResponder, :status => 204
#Recording.delete(params[:recording_id], params[:id], false)
end
###################### FAVORITES ########################
@ -233,7 +211,7 @@ class ApiUsersController < ApiController
respond_with responder: ApiResponder, :status => 204
end
###################### FRIENDS ##########################
###################### FRIENDS (TODO: refactor resource paths) ##########################
def friend_request_index
auth_user(params[:id])
# get all outgoing and incoming friend requests
@ -304,14 +282,5 @@ class ApiUsersController < ApiController
def auth_session_delete
sign_out
render :json => { :success => true }, :status => 200
end
=begin
protected
def auth_user(id)
if current_user.id != id
#respond_with "You do not have permissions to perform this action.", responder: ApiResponder, :status => 403
raise PermissionError, "You do not have permissions to perform this action."
end
end
=end
end
end

View File

@ -0,0 +1,3 @@
object @invitation
extends "api_bands/invitation_show"

View File

@ -0,0 +1,3 @@
object @invitations
extends "api_bands/invitation_show"

View File

@ -0,0 +1,15 @@
object @invitation
attributes :id, :accepted
node :sender do |i|
{ :id => i.sender.id, :name => i.sender.name }
end
node :recipient do |i|
{ :id => i.receiver.id, :name => i.receiver.name }
end
node :band do |i|
{ :id => i.band.id, :name => i.band.name }
end

View File

@ -0,0 +1,3 @@
object @invitations
extends "api_users/band_invitation_show"

View File

@ -0,0 +1,15 @@
object @invitation
attributes :id, :accepted
node :sender do |i|
{ :id => i.sender.id, :name => i.sender.name }
end
node :recipient do |i|
{ :id => i.receiver.id, :name => i.receiver.name }
end
node :band do |i|
{ :id => i.band.id, :name => i.band.name }
end

View File

@ -21,8 +21,8 @@ end
unless @user.instruments.nil? || @user.instruments.size == 0
child :musician_instruments => :instruments do
attributes :description, :proficiency_level, :priority
node :id do |instrument|
instrument.instrument_id
node :instrument_id do |instrument|
instrument.id
end
end
end

View File

@ -3,5 +3,5 @@ object @exception
attributes :message
node "type" do
"ArgumentError"
"ArgumentError"
end

View File

@ -3,5 +3,5 @@ object @exception
attributes :message
node "type" do
"PermissionError"
"PermissionError"
end

View File

@ -3,5 +3,5 @@ object @exception
attributes :message
node "type" do
"StateError"
"StateError"
end

View File

@ -86,8 +86,7 @@ SampleApp::Application.routes.draw do
# user band invitations (NOT DONE)
match '/users/:id/band_invitations' => 'api_users#band_invitation_index', :via => :get
match '/users/:id/band_invitations/:invitation_id' => 'api_users#band_invitation_show', :via => :get, :as => 'api_band_invitation_detail'
match '/users/:id/band_invitations/:band_invitation_id' => 'api_users#band_invitation_update', :via => :post
match '/users/:id/band_invitations/:invitation_id' => 'api_users#band_invitation_show', :via => :get, :as => 'api_user_band_invitation_detail'
# favorites
match '/users/:id/favorites' => 'api_users#favorite_index', :via => :get, :as => 'api_favorite_index'
@ -115,9 +114,11 @@ SampleApp::Application.routes.draw do
match '/bands/:id/recordings/:recording_id' => 'api_bands#recording_update', :via => :post
match '/bands/:id/recordings/:recording_id' => 'api_bands#recording_destroy', :via => :delete
# band invitations (NOT DONE)
# band invitations
match '/bands/:id/invitations' => 'api_bands#invitation_index', :via => :get
match '/bands/:id/invitations/:invitation_id' => 'api_bands#invitation_show', :via => :get, :as => 'api_band_invitation_detail'
match '/bands/:id/invitations' => 'api_bands#invitation_create', :via => :post
match '/bands/:id/invitations/:invitation_id' => 'api_bands#invitation_destroy', :via => :delete
# invitations
match '/invitations/:id' => 'api_invitations#show', :via => :get, :as => 'api_invitation_detail'

View File

@ -18,27 +18,145 @@ describe "Band API", :type => :api do
JSON.parse(last_response.body).should == { "success" => success }
end
context "when logged in as musician" do
it "should allow band creation" do
# ensure creator is member and admin of band
end
################################## BANDS ##################################
def create_band(authenticated_user, name, website, biography, city, state, country, genres)
post "/api/bands.json", { :name => name,
:website => website,
:biography => biography,
:city => city,
:state => state,
:country => country,
:genres => genres
}.to_json,
"CONTENT_TYPE" => 'application/json'
return last_response
end
context "when logged in as musician who is in Band A" do
context "who is band admin" do
it "should allow user to send invitation" do
end
def update_band(authenticated_user, band_id, name, website, biography, city, state, country, genres)
post "/api/bands/#{band_id}.json", { :name => name,
:website => website,
:biography => biography,
:city => city,
:state => state,
:country => country,
:genres => genres
}.to_json,
"CONTENT_TYPE" => 'application/json'
return last_response
end
def get_band(authenticated_user, band_id)
get "/api/bands/#{band_id}.json", "CONTENT_TYPE" => 'application/json'
return last_response
end
########################## RECORDINGS #########################
def create_band_recording(authenticated_user, band_id, description, public)
post "/api/bands/#{band_id}/recordings.json", { :description => description, :public => public }.to_json, "CONTENT_TYPE" => 'application/json'
return last_response
end
def update_band_recording()
end
def get_band_recordings()
end
def get_band_recording()
end
def delete_band_recording()
end
########################## INVITATIONS #########################
def create_band_invitation(authenticated_user, band_id, user_id)
post "/api/bands/#{band_id}/invitations.json", { :band_id => band_id, :user_id => user_id }.to_json, "CONTENT_TYPE" => 'application/json'
return last_response
end
def get_band_invitations(authenticated_user, band_id)
get "/api/bands/#{band_id}/invitations.json", "CONTENT_TYPE" => 'application/json'
return last_response
end
def get_band_invitation(authenticated_user, band_id, invitation_id)
get "/api/bands/#{band_id}/invitations/#{invitation_id}.json", "CONTENT_TYPE" => 'application/json'
return last_response
end
def delete_band_invitation()
end
context "when logged in as musician" do
before(:each) do
login(user.email, user.password, 200, true)
end
context "who is not band admin" do
it "should not allow user to send invitation" do
end
it "should allow band creation" do
last_response = create_band(user, "My Band", "http://www.myband.com", "Bio", "Apex", "NC", "USA", ["african", "hip hop", "country"])
last_response.status.should == 201
new_band = JSON.parse(last_response.body)
new_band["name"].should == "My Band"
last_response = get_band(user, new_band["id"])
last_response.status.should == 200
# ensure creator is member of band after band creation
band_details = JSON.parse(last_response.body)
band_details["id"].should == new_band["id"]
band_details["musicians"][0]["id"].should == user.id
band_details["genres"].size.should == 3
end
it "should prevent bands with less than 1 genre" do
last_response = create_band(user, "My Band", "http://www.myband.com", "Bio", "Apex", "NC", "USA", nil)
last_response.status.should == 400
error_msg = JSON.parse(last_response.body)
error_msg["message"].should == ValidationMessages::GENRE_MINIMUM_NOT_MET
end
it "should prevent bands with more than 3 genres" do
last_response = create_band(user, "My Band", "http://www.myband.com", "Bio", "Apex", "NC", "USA", ["african", "hip hop", "country", "reggae"])
last_response.status.should == 400
error_msg = JSON.parse(last_response.body)
error_msg["message"].should == ValidationMessages::GENRE_LIMIT_EXCEEDED
end
end
context "when logged in as musician who is in Band A" do
before(:each) do
login(user.email, user.password, 200, true)
band.genres << Genre.find("hip hop")
band.genres << Genre.find("african")
band.genres << Genre.find("country")
user.bands << band
end
it "should allow user to update attributes of band A" do
end
band.genres.size.should == 3
it "should allow user to create invitation to band A" do
last_response = update_band(user, band.id, "Brian's Band", "http://www.briansband.com", "Bio", "Apex", "NC", "USA", ["african", "blues"])
last_response.status.should == 200
updated_band = JSON.parse(last_response.body)
# spot check fields in response entity
updated_band["name"].should == "Brian's Band"
updated_band["website"].should == "http://www.briansband.com"
updated_band["genres"].size.should == 2
# retrieve the band to get details
last_response = get_band(user, band.id)
last_response.status.should == 200
band_details = JSON.parse(last_response.body)
band_details["name"].should == "Brian's Band"
band_details["website"].should == "http://www.briansband.com"
band_details["biography"].should == "Bio"
band_details["genres"].size.should == 2
end
it "should allow user to create recording for band A" do
@ -56,11 +174,71 @@ describe "Band API", :type => :api do
it "should allow user to view private recording of Band A" do
end
it "should allow user to see invitation list of band A" do
it "should allow user to create invitation to a Musician for band A" do
recipient = FactoryGirl.create(:user)
last_response = create_band_invitation(user, band.id, recipient.id)
last_response.status.should == 201
invitation = JSON.parse(last_response.body)
# test response entity
invitation["accepted"].nil?.should == true
invitation["sender"]["id"].should == user.id
invitation["recipient"]["id"].should == recipient.id
invitation["band"]["id"].should == band.id
# test receiver relationships
recipient.received_band_invitations.size.should == 1
recipient.sent_band_invitations.size.should == 0
# test sender relationships
user.received_band_invitations.size.should == 0
user.sent_band_invitations.size.should == 1
# test band relationship
band.invitations.size.should == 1
# retrieve invitation list
last_response = get_band_invitations(user, band.id)
last_response.status.should == 200
invitations = JSON.parse(last_response.body)
invitations.size.should == 1
invitations[0]["id"].should == invitation["id"]
invitations[0]["accepted"].nil?.should == true
invitations[0]["sender"]["id"].should == user.id
invitations[0]["recipient"]["id"].should == recipient.id
invitations[0]["band"]["id"].should == band.id
# retrieve invitation details
last_response = get_band_invitation(user, band.id, invitation["id"])
last_response.status.should == 200
invitation_details = JSON.parse(last_response.body)
invitation_details["accepted"].nil?.should == true
invitation_details["sender"]["id"].should == user.id
invitation_details["recipient"]["id"].should == recipient.id
invitation_details["band"]["id"].should == band.id
end
it "should not allow user to create invitation to a Fan for band A" do
recipient = FactoryGirl.create(:fan)
last_response = create_band_invitation(user, band.id, recipient.id)
last_response.status.should == 400
# test receiver relationships
recipient.received_band_invitations.size.should == 0
recipient.sent_band_invitations.size.should == 0
# test sender relationships
user.received_band_invitations.size.should == 0
user.sent_band_invitations.size.should == 0
# test band relationship
band.invitations.size.should == 0
end
end
context "when logged in as musician who is not in band A" do
context "when logged in as user who is not in band A" do
it "should not allow user to update attributes of band A" do
end

View File

@ -8,7 +8,6 @@ describe "Search API", :type => :api do
describe "profile page" do
let(:user) { FactoryGirl.create(:user) }
before(:each) do
Band.delete_search_index
Band.create_search_index
@ -30,8 +29,8 @@ describe "Search API", :type => :api do
User.create_search_index
@musician = FactoryGirl.create(:user, first_name: "Peach", last_name: "Nothing", email: "user@example.com", musician: true)
@fan = FactoryGirl.create(:user, first_name: "Peach Peach", last_name: "Grovery", email: "fan@example.com", musician: false)
@band = Band.save(nil, "Peach pit", "www.bands.com", "zomg we rock", "Apex", "NC", "USA", nil)
@band2 = Band.save(nil, "Peach", "www.bands2.com", "zomg we rock", "Apex", "NC", "USA", nil)
@band = Band.save(nil, "Peach pit", "www.bands.com", "zomg we rock", "Apex", "NC", "USA", ["hip hop"], user.id)
@band2 = Band.save(nil, "Peach", "www.bands2.com", "zomg we rock", "Apex", "NC", "USA", ["hip hop"], user.id)
User.search_index.refresh
Band.search_index.refresh

View File

@ -154,7 +154,7 @@ describe "User API", :type => :api do
# login as fan
login(fan.email, fan.password, 200, true)
# update the user's first name and musician flag'
# update the user's first name and musician flag
post "/api/users/#{fan.id}.json", { :first_name => "Brian", :musician => true }.to_json, "CONTENT_TYPE" => 'application/json'
last_response.status.should == 200
@ -341,6 +341,8 @@ describe "User API", :type => :api do
# get all recordings as non-creator
last_response = get_user_recordings(fan, user)
last_response.status.should == 200
recordings = JSON.parse(last_response.body)
recordings.size.should == 1
recordings[0]["description"].should == public_description