diff --git a/app/controllers/matches_controller.rb b/app/controllers/matches_controller.rb index 549f4d7..10ba52f 100644 --- a/app/controllers/matches_controller.rb +++ b/app/controllers/matches_controller.rb @@ -2,15 +2,43 @@ class MatchesController < ApplicationController before_action :set_match, only: %i[show update] + before_action :validate_params, only: %i[update] + before_action -> { require_owner! @match.owner }, only: %i[update] # GET /matches/1 def show render json: @match, include: ['match_scores.points', 'match_scores.team'] end + # PATCH/PUT /matches/1 + def update + if @match.update(match_params) + render json: @match + else + render json: @match.errors, status: :unprocessable_entity + end + end + private + def validate_params + case match_params['state'] + when 'in_progress' + render json: { error: 'Match can\'t start in this state' }, status: :unprocessable_entity \ + unless @match.not_started? + when 'finished' + render json: { error: 'Match can\'t finish in this state' }, status: :unprocessable_entity \ + unless @match.in_progress? + else + render json: { error: 'Invalid target state' }, status: :unprocessable_entity + end + end + def set_match @match = Match.find(params[:id]) end + + def match_params + params.slice(:state).permit! + end end diff --git a/config/routes.rb b/config/routes.rb index bf135cb..16b79b6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,7 +6,7 @@ Rails.application.routes.draw do sessions: 'overrides/sessions' } - resources :matches, only: %i[show] + resources :matches, only: %i[show update] resources :teams, only: %i[show update] resources :tournaments resources :match_scores, only: %i[show update] diff --git a/spec/controllers/matches_controller_spec.rb b/spec/controllers/matches_controller_spec.rb index 4426afa..10b0a30 100644 --- a/spec/controllers/matches_controller_spec.rb +++ b/spec/controllers/matches_controller_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' RSpec.describe MatchesController, type: :controller do before do - @match = create(:match) + @match = create(:match, state: :not_started) @match.match_scores = create_pair(:match_score) end @@ -22,4 +22,60 @@ RSpec.describe MatchesController, type: :controller do expect(body[:match_scores].map { |ms| ms[:id] }).to eq(@match.match_scores.map(&:id)) end end + + describe 'POST #update' do + let(:valid_update) do + { + state: 'in_progress' + } + end + + let(:invalid_update) do + { + state: 'team1_won' + } + end + + context 'as owner' do + before(:each) do + apply_authentication_headers_for @match.owner + end + + context 'with valid params' do + it 'updates the match' do + put :update, params: { id: @match.to_param }.merge(valid_update) + @match.reload + expect(response).to be_successful + expect(@match.state).to eq(valid_update[:state]) + end + + it 'renders a response with the updated match' do + put :update, params: { id: @match.to_param }.merge(valid_update) + expect(response).to be_successful + body = deserialize_response response + expect(body[:state]).to eq(valid_update[:state]) + end + end + + context 'with invalid params' do + it 'renders an unprocessable entity response' do + put :update, params: { id: @match.to_param }.merge(invalid_update) + expect(response).to have_http_status(:unprocessable_entity) + end + end + end + + context 'as another user' do + context 'with valid params' do + before(:each) do + apply_authentication_headers_for create(:user) + end + + it 'renders a forbidden error response' do + put :update, params: { id: @match.to_param }.merge(valid_update) + expect(response).to have_http_status(:forbidden) + end + end + end + end end