Merge pull request #6 from turniere/ticket/TURNIERE-87
Implement TournamentController
This commit is contained in:
commit
3053b0681e
|
|
@ -24,4 +24,8 @@ class ApplicationController < ActionController::API
|
|||
]
|
||||
}, status: :forbidden
|
||||
end
|
||||
|
||||
def deserialize_params(opts)
|
||||
ActiveModelSerializers::Deserialization.jsonapi_parse(params, opts)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,10 +5,4 @@ class MatchesController < ApplicationController
|
|||
def show
|
||||
render json: Match.find(params[:id]), include: ['scores.score', 'scores.team'], status: status
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def match_params
|
||||
ActiveModelSerializers::Deserialization.jsonapi_parse(params, only: [:state])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,6 +26,6 @@ class TeamsController < ApplicationController
|
|||
end
|
||||
|
||||
def team_params
|
||||
ActiveModelSerializers::Deserialization.jsonapi_parse(params, only: [:name])
|
||||
deserialize_params only: %i[name]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class TournamentsController < ApplicationController
|
||||
before_action :set_tournament, only: %i[show update destroy]
|
||||
before_action :authenticate_user!, only: %i[create update destroy]
|
||||
before_action -> { require_owner! @tournament.owner }, only: %i[update destroy]
|
||||
|
||||
# GET /tournaments
|
||||
def index
|
||||
tournaments = Tournament.where(public: true).or(Tournament.where(owner: current_user)).order(:created_at)
|
||||
render json: tournaments, each_serializer: SimpleTournamentSerializer
|
||||
end
|
||||
|
||||
# GET /tournaments/1
|
||||
def show
|
||||
render json: @tournament
|
||||
end
|
||||
|
||||
# POST /tournaments
|
||||
def create
|
||||
tournament = current_user.tournaments.new tournament_params
|
||||
|
||||
if tournament.save
|
||||
render json: tournament, status: :created, location: tournament
|
||||
else
|
||||
render json: tournament.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
# PATCH/PUT /tournaments/1
|
||||
def update
|
||||
if @tournament.update(tournament_params)
|
||||
render json: @tournament
|
||||
else
|
||||
render json: @tournament.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /tournaments/1
|
||||
def destroy
|
||||
@tournament.destroy
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_tournament
|
||||
@tournament = Tournament.find(params[:id])
|
||||
end
|
||||
|
||||
def tournament_params
|
||||
deserialize_params only: %i[name description public teams]
|
||||
end
|
||||
end
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Team < ApplicationRecord
|
||||
belongs_to :tournament
|
||||
belongs_to :tournament, optional: true
|
||||
has_many :group_scores, dependent: :destroy
|
||||
has_many :scores, dependent: :destroy
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class SimpleTournamentSerializer < ApplicationSerializer
|
||||
attributes :name, :code, :description, :public
|
||||
end
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class TournamentSerializer < SimpleTournamentSerializer
|
||||
has_many :teams
|
||||
has_many :stages
|
||||
end
|
||||
|
|
@ -5,4 +5,5 @@ Rails.application.routes.draw do
|
|||
|
||||
resources :matches, only: %i[show]
|
||||
resources :teams, only: %i[show update]
|
||||
resources :tournaments
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
module AuthHelpers
|
||||
def apply_authentication_headers_for(user)
|
||||
user_headers = user.create_new_auth_token
|
||||
@request.headers.merge!(user_headers)
|
||||
request.headers.merge!(user_headers)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,16 +3,6 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe MatchesController, type: :controller do
|
||||
let(:valid_attributes) do
|
||||
skip('Add a hash of attributes valid for your model')
|
||||
end
|
||||
|
||||
let(:invalid_attributes) do
|
||||
skip('Add a hash of attributes invalid for your model')
|
||||
end
|
||||
|
||||
let(:valid_session) { {} }
|
||||
|
||||
before do
|
||||
@match = create(:match)
|
||||
@match.scores = create_pair(:score)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,205 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe TournamentsController, type: :controller do
|
||||
def tournament_ids(response)
|
||||
deserialize_list(response).map { |t| t[:id].to_i }
|
||||
end
|
||||
before do
|
||||
@tournament = create(:tournament)
|
||||
@user = @tournament.owner
|
||||
@another_user = create(:user)
|
||||
@private_tournament = create(:tournament, user: @another_user, public: false)
|
||||
@teams = create_list(:detached_team, 4)
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns a success response' do
|
||||
get :index
|
||||
expect(response).to be_successful
|
||||
end
|
||||
|
||||
it 'returns all public tournaments' do
|
||||
get :index
|
||||
tournaments = deserialize_list response
|
||||
public_tournaments = tournaments.select { |t| t[:public] }
|
||||
expect(public_tournaments.size).to eq((Tournament.where public: true).size)
|
||||
end
|
||||
|
||||
it 'returns no private tournaments for unauthenticated users' do
|
||||
get :index
|
||||
tournaments = deserialize_list response
|
||||
private_tournaments = tournaments.reject { |t| t[:public] }
|
||||
expect(private_tournaments.size).to eq(0)
|
||||
end
|
||||
|
||||
it 'returns private tournaments owned by the authenticated user' do
|
||||
apply_authentication_headers_for @another_user
|
||||
get :index
|
||||
expect(tournament_ids(response)).to include(@private_tournament.id)
|
||||
end
|
||||
|
||||
it 'returns no private tournaments owned by another user' do
|
||||
apply_authentication_headers_for @user
|
||||
get :index
|
||||
expect(tournament_ids(response)).not_to include(@private_tournament.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns a success response' do
|
||||
get :show, params: { id: @tournament.to_param }
|
||||
expect(response).to be_successful
|
||||
end
|
||||
|
||||
it 'returns the requested tournament' do
|
||||
get :show, params: { id: @tournament.to_param }
|
||||
expect(deserialize_response(response)[:id].to_i).to eq(@tournament.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:create_data) do
|
||||
{
|
||||
data: {
|
||||
type: 'tournaments',
|
||||
attributes: {
|
||||
name: Faker::Dog.name,
|
||||
description: Faker::Lorem.sentence,
|
||||
public: false
|
||||
},
|
||||
relationships: {
|
||||
teams: {
|
||||
data: @teams.map { |team| { type: 'teams', id: team.id } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
apply_authentication_headers_for @user
|
||||
end
|
||||
|
||||
context 'with valid params' do
|
||||
it 'creates a new Tournament' do
|
||||
expect do
|
||||
post :create, params: create_data
|
||||
end.to change(Tournament, :count).by(1)
|
||||
end
|
||||
|
||||
it 'associates the new tournament with the authenticated user' do
|
||||
expect do
|
||||
post :create, params: create_data
|
||||
end.to change(@user.tournaments, :size).by(1)
|
||||
end
|
||||
|
||||
it 'associates the given teams with the created tournament' do
|
||||
new_teams = create_list(:detached_team, 4)
|
||||
new_teams_create_data = create_data
|
||||
new_teams_create_data[:data][:relationships][:teams][:data] = \
|
||||
new_teams.map { |team| { type: 'teams', id: team.id } }
|
||||
post :create, params: new_teams_create_data
|
||||
expect(Tournament.last.teams).to match_array(new_teams)
|
||||
end
|
||||
|
||||
it 'renders a JSON response with the new tournament' do
|
||||
post :create, params: create_data
|
||||
expect(response).to have_http_status(:created)
|
||||
expect(response.content_type).to eq('application/json')
|
||||
expect(response.location).to eq(tournament_url(Tournament.last))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
let(:valid_update) do
|
||||
{
|
||||
data: {
|
||||
type: 'tournaments',
|
||||
id: @tournament.id,
|
||||
attributes: {
|
||||
name: Faker::Dog.name
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context 'with valid params' do
|
||||
context 'without authentication headers' do
|
||||
it 'renders a unauthorized error response' do
|
||||
put :update, params: { id: @tournament.to_param }.merge(valid_update)
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'as owner' do
|
||||
before(:each) do
|
||||
apply_authentication_headers_for @tournament.owner
|
||||
end
|
||||
|
||||
it 'updates the requested tournament' do
|
||||
put :update, params: { id: @tournament.to_param }.merge(valid_update)
|
||||
@tournament.reload
|
||||
expect(@tournament.name).to eq(valid_update[:data][:attributes][:name])
|
||||
end
|
||||
|
||||
it 'renders a JSON response with the tournament' do
|
||||
put :update, params: { id: @tournament.to_param }.merge(valid_update)
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(response.content_type).to eq('application/json')
|
||||
end
|
||||
end
|
||||
|
||||
context 'as another user' do
|
||||
before do
|
||||
apply_authentication_headers_for create(:user)
|
||||
end
|
||||
|
||||
it 'renders a forbidden error response' do
|
||||
put :update, params: { id: @tournament.to_param }.merge(valid_update)
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
context 'without authentication headers' do
|
||||
it 'renders a unauthorized error response' do
|
||||
delete :destroy, params: { id: @tournament.to_param }
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'as owner' do
|
||||
before(:each) do
|
||||
apply_authentication_headers_for @tournament.owner
|
||||
end
|
||||
|
||||
it 'destroys the requested tournament' do
|
||||
expect do
|
||||
delete :destroy, params: { id: @tournament.to_param }
|
||||
end.to change(Tournament, :count).by(-1)
|
||||
end
|
||||
|
||||
it 'destroys associated teams' do
|
||||
expect do
|
||||
delete :destroy, params: { id: @tournament.to_param }
|
||||
end.to change(Team, :count).by(-@tournament.teams.size)
|
||||
end
|
||||
end
|
||||
|
||||
context 'as another user' do
|
||||
before do
|
||||
apply_authentication_headers_for create(:user)
|
||||
end
|
||||
|
||||
it 'renders a forbidden error response' do
|
||||
delete :destroy, params: { id: @tournament.to_param }
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -4,4 +4,10 @@ module DeserializeHelpers
|
|||
def deserialize_response(response)
|
||||
ActiveModelSerializers::Deserialization.jsonapi_parse(JSON.parse(response.body))
|
||||
end
|
||||
|
||||
def deserialize_list(response)
|
||||
JSON.parse(response.body, symbolize_names: true)[:data].map do |raw_obj|
|
||||
raw_obj[:attributes].merge raw_obj.except(:attributes)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,4 +5,8 @@ FactoryBot.define do
|
|||
name { Faker::Dog.name }
|
||||
tournament
|
||||
end
|
||||
|
||||
factory :detached_team, class: Team do
|
||||
name { Faker::Dog.name }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe TournamentsController, type: :routing do
|
||||
describe 'routing' do
|
||||
it 'routes to #index' do
|
||||
expect(get: '/tournaments').to route_to('tournaments#index')
|
||||
end
|
||||
|
||||
it 'routes to #show' do
|
||||
expect(get: '/tournaments/1').to route_to('tournaments#show', id: '1')
|
||||
end
|
||||
|
||||
it 'routes to #create' do
|
||||
expect(post: '/tournaments').to route_to('tournaments#create')
|
||||
end
|
||||
|
||||
it 'routes to #update via PUT' do
|
||||
expect(put: '/tournaments/1').to route_to('tournaments#update', id: '1')
|
||||
end
|
||||
|
||||
it 'routes to #update via PATCH' do
|
||||
expect(patch: '/tournaments/1').to route_to('tournaments#update', id: '1')
|
||||
end
|
||||
|
||||
it 'routes to #destroy' do
|
||||
expect(delete: '/tournaments/1').to route_to('tournaments#destroy', id: '1')
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue