fix(ci): restore Rails 8 spec suite

Confirm factory users for real Devise auth in request specs and use Rails 8-compatible status and route calls to remove deprecation warnings.
This commit is contained in:
Daniel Schädler 2026-04-29 15:48:20 +02:00
parent 8855532660
commit 6df5cb2502
20 changed files with 136 additions and 76 deletions

View File

@ -36,7 +36,7 @@ class BeamersController < ApplicationController
push_sync_if_needed! push_sync_if_needed!
render json: beamer, status: :created render json: beamer, status: :created
else else
render json: beamer.errors, status: :unprocessable_entity render json: beamer.errors, status: :unprocessable_content
end end
end end
@ -46,7 +46,7 @@ class BeamersController < ApplicationController
push_sync_if_needed! push_sync_if_needed!
render json: @beamer render json: @beamer
else else
render json: @beamer.errors, status: :unprocessable_entity render json: @beamer.errors, status: :unprocessable_content
end end
end end

View File

@ -25,6 +25,6 @@ class BetsController < ApplicationController
end end
def handle_user_service_error(exception) def handle_user_service_error(exception)
render json: { error: exception.message }, status: :unprocessable_entity render json: { error: exception.message }, status: :unprocessable_content
end end
end end

View File

@ -19,7 +19,7 @@ class MatchScoresController < ApplicationController
TournamentLiveBroadcast.call(@match_score.tournament.id) TournamentLiveBroadcast.call(@match_score.tournament.id)
render json: @match_score render json: @match_score
else else
render json: @match_score.errors, status: :unprocessable_entity render json: @match_score.errors, status: :unprocessable_content
end end
end end

View File

@ -26,14 +26,14 @@ class MatchesController < ApplicationController
match = build_decider_match match = build_decider_match
if match.errors.any? if match.errors.any?
render json: match.errors, status: :unprocessable_entity render json: match.errors, status: :unprocessable_content
elsif match.save elsif match.save
UpdateGroupsGroupScoresAndSave.call(group: @group) UpdateGroupsGroupScoresAndSave.call(group: @group)
push_sync_if_needed!(@group.tournament) push_sync_if_needed!(@group.tournament)
TournamentLiveBroadcast.call(@group.tournament.id) TournamentLiveBroadcast.call(@group.tournament.id)
render json: match, include: %w[match_scores.team group], status: :created render json: match, include: %w[match_scores.team group], status: :created
else else
render json: match.errors, status: :unprocessable_entity render json: match.errors, status: :unprocessable_content
end end
end end
@ -55,7 +55,7 @@ class MatchesController < ApplicationController
render json: @match render json: @match
synced_tournament = @match.tournament synced_tournament = @match.tournament
else else
render json: @match.errors, status: :unprocessable_entity render json: @match.errors, status: :unprocessable_content
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
end end
@ -66,7 +66,7 @@ class MatchesController < ApplicationController
# PATCH /matches/1/swap # PATCH /matches/1/swap
def swap def swap
unless @match.swappable_with?(@swap_target) unless @match.swappable_with?(@swap_target)
render json: { error: 'Matches must be different group matches from the same group' }, status: :unprocessable_entity render json: { error: 'Matches must be different group matches from the same group' }, status: :unprocessable_content
return return
end end
@ -102,27 +102,27 @@ class MatchesController < ApplicationController
if @match.winner.nil? if @match.winner.nil?
render json: { error: 'Stopping undecided Matches isn\'t allowed in playoff stage' }, render json: { error: 'Stopping undecided Matches isn\'t allowed in playoff stage' },
status: :unprocessable_entity status: :unprocessable_content
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
return if PopulateMatchBelowAndSave.call(match: @match).success? return if PopulateMatchBelowAndSave.call(match: @match).success?
render json: { error: 'Moving Team one stage down failed' }, render json: { error: 'Moving Team one stage down failed' },
status: :unprocessable_entity status: :unprocessable_content
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
def validate_params def validate_params
case match_params['state'] case match_params['state']
when 'in_progress' when 'in_progress'
render json: { error: 'Match can\'t start in this state' }, status: :unprocessable_entity \ render json: { error: 'Match can\'t start in this state' }, status: :unprocessable_content \
unless @match.not_started? unless @match.not_started?
when 'finished' when 'finished'
render json: { error: 'Match can\'t finish in this state' }, status: :unprocessable_entity \ render json: { error: 'Match can\'t finish in this state' }, status: :unprocessable_content \
unless @match.in_progress? unless @match.in_progress?
else else
render json: { error: 'Invalid target state' }, status: :unprocessable_entity render json: { error: 'Invalid target state' }, status: :unprocessable_content
end end
end end

View File

@ -15,7 +15,7 @@ class StagesController < ApplicationController
def update def update
if stage_params[:state] == 'finished' if stage_params[:state] == 'finished'
unless @stage.state == 'in_progress' unless @stage.state == 'in_progress'
render json: { error: 'Only running group stages can be finished' }, status: :unprocessable_entity render json: { error: 'Only running group stages can be finished' }, status: :unprocessable_content
return return
end end
@ -27,7 +27,7 @@ class StagesController < ApplicationController
render json: @stage render json: @stage
synced_tournament = @stage.tournament synced_tournament = @stage.tournament
else else
render json: @stage.errors, status: :unprocessable_entity render json: @stage.errors, status: :unprocessable_content
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
end end
@ -36,7 +36,7 @@ class StagesController < ApplicationController
else else
render json: { render json: {
error: 'The state attribute may only be changed to finished' error: 'The state attribute may only be changed to finished'
}, status: :unprocessable_entity }, status: :unprocessable_content
end end
end end
@ -46,14 +46,14 @@ class StagesController < ApplicationController
unless @stage.over? unless @stage.over?
render json: { render json: {
error: 'Group Stage still has some matches that are not over yet. Finish them to generate playoffs' error: 'Group Stage still has some matches that are not over yet. Finish them to generate playoffs'
}, status: :unprocessable_entity }, status: :unprocessable_content
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
@stage.groups.each do |group| @stage.groups.each do |group|
next if UpdateGroupsGroupScoresAndSave.call(group: group).success? next if UpdateGroupsGroupScoresAndSave.call(group: group).success?
render json: { error: 'Updating group scores failed' }, status: :unprocessable_entity render json: { error: 'Updating group scores failed' }, status: :unprocessable_content
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
@ -62,14 +62,14 @@ class StagesController < ApplicationController
render json: { render json: {
error: 'Playoffs cannot be generated yet because a decider match is required for an advancing place', error: 'Playoffs cannot be generated yet because a decider match is required for an advancing place',
blocking_ties: blocking_ties blocking_ties: blocking_ties
}, status: :unprocessable_entity }, status: :unprocessable_content
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
return if AddPlayoffsToTournamentAndSave.call(tournament: @stage.tournament, return if AddPlayoffsToTournamentAndSave.call(tournament: @stage.tournament,
teams: GroupStageService.get_advancing_teams(@stage)).success? teams: GroupStageService.get_advancing_teams(@stage)).success?
render json: { error: 'Generating group stage failed' }, status: :unprocessable_entity render json: { error: 'Generating group stage failed' }, status: :unprocessable_content
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end

View File

@ -15,7 +15,7 @@ class TeamActionItemsController < ApplicationController
) )
render json: @team_action_item render json: @team_action_item
else else
render json: @team_action_item.errors, status: :unprocessable_entity render json: @team_action_item.errors, status: :unprocessable_content
end end
end end

View File

@ -20,9 +20,9 @@ class TeamActionListsController < ApplicationController
render json: team_action_list, status: :created render json: team_action_list, status: :created
rescue TeamActionListService::InvalidSourceError, TeamActionListService::EmptySourceError => e rescue TeamActionListService::InvalidSourceError, TeamActionListService::EmptySourceError => e
render json: { error: e.message }, status: :unprocessable_entity render json: { error: e.message }, status: :unprocessable_content
rescue ActiveRecord::RecordInvalid => e rescue ActiveRecord::RecordInvalid => e
render json: e.record.errors, status: :unprocessable_entity render json: e.record.errors, status: :unprocessable_content
end end
# PATCH /tournaments/:tournament_id/team_action_lists/:key/teams/:team_id # PATCH /tournaments/:tournament_id/team_action_lists/:key/teams/:team_id
@ -33,7 +33,7 @@ class TeamActionListsController < ApplicationController
) )
render json: @team_action_item render json: @team_action_item
else else
render json: @team_action_item.errors, status: :unprocessable_entity render json: @team_action_item.errors, status: :unprocessable_content
end end
end end

View File

@ -17,7 +17,7 @@ class TeamsController < ApplicationController
push_sync_if_needed!(@team.tournament) push_sync_if_needed!(@team.tournament)
render json: @team render json: @team
else else
render json: @team.errors, status: :unprocessable_entity render json: @team.errors, status: :unprocessable_content
end end
end end

View File

@ -67,7 +67,7 @@ class TournamentsController < ApplicationController
if tournament.save if tournament.save
render json: tournament, status: :created, location: tournament render json: tournament, status: :created, location: tournament
else else
render json: tournament.errors, status: :unprocessable_entity render json: tournament.errors, status: :unprocessable_content
end end
return return
end end
@ -90,14 +90,14 @@ class TournamentsController < ApplicationController
end end
# validate tournament # validate tournament
unless tournament.valid? unless tournament.valid?
render json: tournament.errors, status: :unprocessable_entity render json: tournament.errors, status: :unprocessable_content
return return
end end
# return appropriate result # return appropriate result
if result.success? if result.success?
render json: result.tournament, status: :created, location: result.tournament render json: result.tournament, status: :created, location: result.tournament
else else
render json: { error: 'Tournament generation failed' }, status: :unprocessable_entity render json: { error: 'Tournament generation failed' }, status: :unprocessable_content
end end
end end
@ -116,7 +116,7 @@ class TournamentsController < ApplicationController
synced_tournament = @tournament synced_tournament = @tournament
render json: @tournament render json: @tournament
else else
render json: @tournament.errors, status: :unprocessable_entity render json: @tournament.errors, status: :unprocessable_content
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
end end
@ -139,7 +139,7 @@ class TournamentsController < ApplicationController
push_sync_if_needed!(@tournament) push_sync_if_needed!(@tournament)
render json: @tournament render json: @tournament
else else
render json: @tournament.errors, status: :unprocessable_entity render json: @tournament.errors, status: :unprocessable_content
end end
end end
@ -148,14 +148,14 @@ class TournamentsController < ApplicationController
TournamentLiveBroadcast.call(@tournament.id) TournamentLiveBroadcast.call(@tournament.id)
render json: @tournament, include: '**' render json: @tournament, include: '**'
rescue KeyError, ArgumentError => e rescue KeyError, ArgumentError => e
render json: { error: e.message }, status: :unprocessable_entity render json: { error: e.message }, status: :unprocessable_content
end end
def test_sync def test_sync
unless @tournament.sync_push_enabled? unless @tournament.sync_push_enabled?
return render json: { return render json: {
error: 'Tournament sync test requires writable tournament with sync_target_url and sync_auth_token' error: 'Tournament sync test requires writable tournament with sync_target_url and sync_auth_token'
}, status: :unprocessable_entity }, status: :unprocessable_content
end end
TournamentSyncPusher.push!(@tournament) TournamentSyncPusher.push!(@tournament)
@ -276,7 +276,7 @@ class TournamentsController < ApplicationController
teams = params['teams'] teams = params['teams']
return if teams.is_a?(Array) && teams.reject { |t| t.is_a? ActionController::Parameters }.count.zero? return if teams.is_a?(Array) && teams.reject { |t| t.is_a? ActionController::Parameters }.count.zero?
render json: { error: 'Invalid teams array' }, status: :unprocessable_entity render json: { error: 'Invalid teams array' }, status: :unprocessable_content
end end
def only_playoff_teams_amount_changed def only_playoff_teams_amount_changed
@ -307,14 +307,14 @@ class TournamentsController < ApplicationController
render json: { render json: {
error: 'playoff_teams_amount, instant_finalists_amount and intermediate_round_participants_amount don\'t match' error: 'playoff_teams_amount, instant_finalists_amount and intermediate_round_participants_amount don\'t match'
}, status: :unprocessable_entity }, status: :unprocessable_content
end end
def sync_state_params def sync_state_params
params.require(:snapshot).permit!.to_h params.require(:snapshot).permit!.to_h
end end
def authorize_sync_request! def authorize_sync_request!
return render json: { error: 'Tournament is not configured to accept sync pushes' }, status: :unprocessable_entity unless @tournament.sync_accepts_push? return render json: { error: 'Tournament is not configured to accept sync pushes' }, status: :unprocessable_content unless @tournament.sync_accepts_push?
token = request.authorization.to_s.delete_prefix('Bearer ').presence || request.headers['X-Tournament-Sync-Token'].to_s token = request.authorization.to_s.delete_prefix('Bearer ').presence || request.headers['X-Tournament-Sync-Token'].to_s
return render json: { error: 'Missing sync token' }, status: :unauthorized if token.blank? return render json: { error: 'Missing sync token' }, status: :unauthorized if token.blank?
@ -448,12 +448,12 @@ class TournamentsController < ApplicationController
return 'timer_reason_text is required for custom timer_reason' return 'timer_reason_text is required for custom timer_reason'
end end
if timer_reason != 'custom' && timer_reason_text.present? return unless timer_reason != 'custom' && timer_reason_text.present?
'timer_reason_text is only allowed when timer_reason is custom' 'timer_reason_text is only allowed when timer_reason is custom'
end end
end
def render_timer_validation_error(message) def render_timer_validation_error(message)
render json: { error: message }, status: :unprocessable_entity render json: { error: message }, status: :unprocessable_content
end end
end end

View File

@ -0,0 +1,53 @@
# frozen_string_literal: true
# Devise 4.9 still passes route option hashes to Rails' `resource` helper
# positionally. Rails 8.1 accepts that with deprecation warnings and Rails 8.2
# removes it, so keep the same Devise routes but pass those options as keywords.
module DeviseRoutesRails8Compat
def devise_session(mapping, controllers)
resource :session, only: [], controller: controllers[:sessions], path: '' do
get :new, path: mapping.path_names[:sign_in], as: 'new'
post :create, path: mapping.path_names[:sign_in]
match :destroy, path: mapping.path_names[:sign_out], as: 'destroy', via: mapping.sign_out_via
end
end
def devise_password(mapping, controllers)
resource :password,
only: [:new, :create, :edit, :update],
path: mapping.path_names[:password],
controller: controllers[:passwords]
end
def devise_confirmation(mapping, controllers)
resource :confirmation,
only: [:new, :create, :show],
path: mapping.path_names[:confirmation],
controller: controllers[:confirmations]
end
def devise_unlock(mapping, controllers)
return unless mapping.to.unlock_strategy_enabled?(:email)
resource :unlock,
only: [:new, :create, :show],
path: mapping.path_names[:unlock],
controller: controllers[:unlocks]
end
def devise_registration(mapping, controllers)
resource :registration,
only: [:new, :create, :edit, :update, :destroy],
path: mapping.path_names[:registration],
path_names: {
new: mapping.path_names[:sign_up],
edit: mapping.path_names[:edit],
cancel: mapping.path_names[:cancel]
},
controller: controllers[:registrations] do
get :cancel
end
end
end
ActionDispatch::Routing::Mapper.prepend(DeviseRoutesRails8Compat)

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
class AddTimerReasonToTournaments < ActiveRecord::Migration[7.0] class AddTimerReasonToTournaments < ActiveRecord::Migration[7.0]
def change def change
add_column :tournaments, :timer_reason, :string add_column :tournaments, :timer_reason, :string

View File

@ -95,14 +95,14 @@ RSpec.describe BeamersController, type: :controller do
post :create, params: { post :create, params: {
tournament_id: @tournament.to_param, name: 'bad', display_state: 'invalid' tournament_id: @tournament.to_param, name: 'bad', display_state: 'invalid'
} }
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
it 'rejects duplicate name in same tournament' do it 'rejects duplicate name in same tournament' do
post :create, params: { post :create, params: {
tournament_id: @tournament.to_param, name: @beamer.name, display_state: 'during_game' tournament_id: @tournament.to_param, name: @beamer.name, display_state: 'during_game'
} }
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end
@ -157,7 +157,7 @@ RSpec.describe BeamersController, type: :controller do
tournament_id: @tournament.to_param, id: @beamer.to_param, tournament_id: @tournament.to_param, id: @beamer.to_param,
display_state: 'bogus' display_state: 'bogus'
} }
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end

View File

@ -62,7 +62,7 @@ RSpec.describe MatchScoresController, type: :controller do
it 'returns unprocessable entity' do it 'returns unprocessable entity' do
put :update, params: { id: @match_score.to_param }.merge(valid_update) put :update, params: { id: @match_score.to_param }.merge(valid_update)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end
end end

View File

@ -120,7 +120,7 @@ RSpec.describe MatchesController, type: :controller do
it 'rejects the request' do it 'rejects the request' do
post :create, params: { group_id: group.to_param, team_ids: [group.teams.first.id] } post :create, params: { group_id: group.to_param, team_ids: [group.teams.first.id] }
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end
end end
@ -167,7 +167,7 @@ RSpec.describe MatchesController, type: :controller do
patch :swap, params: { id: first_match.to_param, other_match_id: foreign_match.to_param } patch :swap, params: { id: first_match.to_param, other_match_id: foreign_match.to_param }
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
expect(deserialize_response(response)[:error]).to eq('Matches must be different group matches from the same group') expect(deserialize_response(response)[:error]).to eq('Matches must be different group matches from the same group')
end end
@ -288,7 +288,7 @@ RSpec.describe MatchesController, type: :controller do
end end
it 'returns an unprocessable entity response' do it 'returns an unprocessable entity response' do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
it 'doesn\'t change the matches status' do it 'doesn\'t change the matches status' do
@ -321,7 +321,7 @@ RSpec.describe MatchesController, type: :controller do
it 'returns unprocessable entity' do it 'returns unprocessable entity' do
put :update, params: { id: @running_playoff_match.to_param }.merge(finished) put :update, params: { id: @running_playoff_match.to_param }.merge(finished)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end
@ -341,7 +341,7 @@ RSpec.describe MatchesController, type: :controller do
allow_any_instance_of(Match).to receive(:winner).and_return(@running_playoff_match.match_scores.first.team) allow_any_instance_of(Match).to receive(:winner).and_return(@running_playoff_match.match_scores.first.team)
put :update, params: { id: @running_playoff_match.to_param }.merge(finished) put :update, params: { id: @running_playoff_match.to_param }.merge(finished)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end
end end
@ -375,14 +375,14 @@ RSpec.describe MatchesController, type: :controller do
context 'with invalid params' do context 'with invalid params' do
it 'renders an unprocessable entity response' do it 'renders an unprocessable entity response' do
put :update, params: { id: @match.to_param }.merge(invalid_update) put :update, params: { id: @match.to_param }.merge(invalid_update)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end
context 'with senseless params' do context 'with senseless params' do
it 'renders an unprocessable entity response' do it 'renders an unprocessable entity response' do
put :update, params: { id: @match.to_param }.merge(senseless_update) put :update, params: { id: @match.to_param }.merge(senseless_update)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end
end end
@ -416,7 +416,7 @@ RSpec.describe MatchesController, type: :controller do
context 'with invalid params' do context 'with invalid params' do
it 'renders an unprocessable entity response' do it 'renders an unprocessable entity response' do
put :update, params: { id: @not_ready_playoff_match.to_param }.merge(invalid_update) put :update, params: { id: @not_ready_playoff_match.to_param }.merge(invalid_update)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end
end end

View File

@ -122,7 +122,7 @@ RSpec.describe StagesController, type: :controller do
end end
it 'it returns unprocessable entity' do it 'it returns unprocessable entity' do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
it 'returns the correct error' do it 'returns the correct error' do
@ -145,7 +145,7 @@ RSpec.describe StagesController, type: :controller do
end end
it 'it returns unprocessable entity' do it 'it returns unprocessable entity' do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
it 'returns the correct error' do it 'returns the correct error' do
@ -164,7 +164,7 @@ RSpec.describe StagesController, type: :controller do
end end
it 'it returns unprocessable entity' do it 'it returns unprocessable entity' do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
it 'returns the correct error' do it 'returns the correct error' do
@ -197,7 +197,7 @@ RSpec.describe StagesController, type: :controller do
end end
it 'returns unprocessable entity' do it 'returns unprocessable entity' do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
it 'returns a helpful decider error' do it 'returns a helpful decider error' do
@ -233,7 +233,7 @@ RSpec.describe StagesController, type: :controller do
end end
it 'returns unprocessable entity' do it 'returns unprocessable entity' do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
it 'returns a helpful decider error' do it 'returns a helpful decider error' do

View File

@ -47,7 +47,7 @@ RSpec.describe TeamActionListsController, type: :controller do
it 'returns unprocessable entity for unsupported source' do it 'returns unprocessable entity for unsupported source' do
post :create, params: create_params.merge(source: 'unknown_source') post :create, params: create_params.merge(source: 'unknown_source')
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
expect(deserialize_response(response)[:error]).to eq('Unsupported team action list source: unknown_source') expect(deserialize_response(response)[:error]).to eq('Unsupported team action list source: unknown_source')
end end
@ -57,7 +57,7 @@ RSpec.describe TeamActionListsController, type: :controller do
post :create, params: create_params.merge(tournament_id: empty_tournament.to_param) post :create, params: create_params.merge(tournament_id: empty_tournament.to_param)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
expect(deserialize_response(response)[:error]).to eq('Source all_tournament_teams does not currently contain any teams') expect(deserialize_response(response)[:error]).to eq('Source all_tournament_teams does not currently contain any teams')
end end
@ -71,7 +71,7 @@ RSpec.describe TeamActionListsController, type: :controller do
post :create, params: create_params post :create, params: create_params
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end

View File

@ -308,21 +308,21 @@ RSpec.describe TournamentsController, type: :controller do
it 'rejects timestamp_seconds for countup mode' do it 'rejects timestamp_seconds for countup mode' do
patch :set_timer, params: { id: @tournament.to_param, timer_mode: 'countup', timestamp_seconds: 120 } patch :set_timer, params: { id: @tournament.to_param, timer_mode: 'countup', timestamp_seconds: 120 }
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
expect(deserialize_response(response)[:error]).to eq('timestamp_seconds is only allowed for countdown mode') expect(deserialize_response(response)[:error]).to eq('timestamp_seconds is only allowed for countdown mode')
end end
it 'rejects invalid timer reason values' do it 'rejects invalid timer reason values' do
patch :set_timer, params: { id: @tournament.to_param, timestamp_seconds: 120, timer_reason: 'ceremony' } patch :set_timer, params: { id: @tournament.to_param, timestamp_seconds: 120, timer_reason: 'ceremony' }
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
expect(deserialize_response(response)[:error]).to eq('Invalid timer_reason') expect(deserialize_response(response)[:error]).to eq('Invalid timer_reason')
end end
it 'requires timer_reason_text for custom timer reason' do it 'requires timer_reason_text for custom timer reason' do
patch :set_timer, params: { id: @tournament.to_param, timestamp_seconds: 120, timer_reason: 'custom' } patch :set_timer, params: { id: @tournament.to_param, timestamp_seconds: 120, timer_reason: 'custom' }
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
expect(deserialize_response(response)[:error]).to eq('timer_reason_text is required for custom timer_reason') expect(deserialize_response(response)[:error]).to eq('timer_reason_text is required for custom timer_reason')
end end
@ -334,7 +334,7 @@ RSpec.describe TournamentsController, type: :controller do
timer_reason_text: 'Extra info' timer_reason_text: 'Extra info'
} }
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
expect(deserialize_response(response)[:error]).to eq( expect(deserialize_response(response)[:error]).to eq(
'timer_reason_text is only allowed when timer_reason is custom' 'timer_reason_text is only allowed when timer_reason is custom'
) )
@ -466,7 +466,7 @@ RSpec.describe TournamentsController, type: :controller do
context 'playoff_teams_amount unacceptable' do context 'playoff_teams_amount unacceptable' do
shared_examples_for 'wrong playoff_teams_amount' do shared_examples_for 'wrong playoff_teams_amount' do
it 'fails' do it 'fails' do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
it 'returns the correct error message' do it 'returns the correct error message' do
expect(deserialize_response(response)[:playoff_teams_amount].first) expect(deserialize_response(response)[:playoff_teams_amount].first)
@ -522,7 +522,7 @@ RSpec.describe TournamentsController, type: :controller do
data = create_group_tournament_data data = create_group_tournament_data
data[:teams].pop data[:teams].pop
post :create, params: data post :create, params: data
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end
@ -540,7 +540,7 @@ RSpec.describe TournamentsController, type: :controller do
context 'with invalid parameters' do context 'with invalid parameters' do
it 'renders an unprocessable entity response' do it 'renders an unprocessable entity response' do
put :create, params: { teams: [1, 2, 3] } put :create, params: { teams: [1, 2, 3] }
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end
@ -549,7 +549,7 @@ RSpec.describe TournamentsController, type: :controller do
data = create_group_tournament_data data = create_group_tournament_data
data[:teams] = [{ group: 1 }, { group: 1 }, { group: 2 }, { group: 2 }] data[:teams] = [{ group: 1 }, { group: 1 }, { group: 2 }, { group: 2 }]
post :create, params: data post :create, params: data
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end
end end
@ -637,18 +637,18 @@ RSpec.describe TournamentsController, type: :controller do
it 'fails when only instant_finalists_amount is changed' do it 'fails when only instant_finalists_amount is changed' do
put :update, params: { id: @filled_tournament.to_param }.merge(instant_finalists_amount: 29) put :update, params: { id: @filled_tournament.to_param }.merge(instant_finalists_amount: 29)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
it 'fails when only intermediate_round_participants_amount is changed' do it 'fails when only intermediate_round_participants_amount is changed' do
put :update, params: { id: @filled_tournament.to_param }.merge(intermediate_round_participants_amount: 29) put :update, params: { id: @filled_tournament.to_param }.merge(intermediate_round_participants_amount: 29)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
it 'fails when parameters don\'t match' do it 'fails when parameters don\'t match' do
put :update, params: { id: @filled_tournament.to_param }.merge(intermediate_round_participants_amount: 29, put :update, params: { id: @filled_tournament.to_param }.merge(intermediate_round_participants_amount: 29,
instant_finalists_amount: 32) instant_finalists_amount: 32)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
it 'succeeds when all three are changed correctly' do it 'succeeds when all three are changed correctly' do
@ -667,7 +667,7 @@ RSpec.describe TournamentsController, type: :controller do
it 'returns unprocessable entity' do it 'returns unprocessable entity' do
put :update, params: { id: @filled_tournament.to_param }.merge(playoff_teams_amount: 8) put :update, params: { id: @filled_tournament.to_param }.merge(playoff_teams_amount: 8)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
it 'doesn\'t change playoff_teams_amount' do it 'doesn\'t change playoff_teams_amount' do
@ -720,7 +720,7 @@ RSpec.describe TournamentsController, type: :controller do
it 'fails when playoff_teams_amount is higher than the amount of teams participating' do it 'fails when playoff_teams_amount is higher than the amount of teams participating' do
put :update, params: { id: @filled_tournament.to_param }.merge(playoff_teams_amount: 783) put :update, params: { id: @filled_tournament.to_param }.merge(playoff_teams_amount: 783)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
end end
end end
end end
@ -863,7 +863,7 @@ RSpec.describe TournamentsController, type: :controller do
it 'rejects sync test without complete leader configuration' do it 'rejects sync test without complete leader configuration' do
post :test_sync, params: { id: @tournament.to_param } post :test_sync, params: { id: @tournament.to_param }
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_content)
expect(deserialize_response(response)[:error]) expect(deserialize_response(response)[:error])
.to eq('Tournament sync test requires writable tournament with sync_target_url and sync_auth_token') .to eq('Tournament sync test requires writable tournament with sync_target_url and sync_auth_token')
end end

View File

@ -5,5 +5,6 @@ FactoryBot.define do
sequence(:username) { |n| "user#{n}" } sequence(:username) { |n| "user#{n}" }
sequence(:email) { |n| "user#{n}@example.com" } sequence(:email) { |n| "user#{n}@example.com" }
password { 'password123' } password { 'password123' }
confirmed_at { Time.current }
end end
end end

View File

@ -80,6 +80,7 @@ RSpec.describe TournamentSnapshotImporter do
end end
end end
# rubocop:disable Metrics/MethodLength
def create_large_source_tournament! def create_large_source_tournament!
tournament = create( tournament = create(
:tournament, :tournament,
@ -142,6 +143,7 @@ RSpec.describe TournamentSnapshotImporter do
) )
tournament.reload tournament.reload
end end
# rubocop:enable Metrics/MethodLength
def create_group_round_robin!(group:, teams:) def create_group_round_robin!(group:, teams:)
pairings = [ pairings = [
@ -190,6 +192,7 @@ RSpec.describe TournamentSnapshotImporter do
end end
end end
# rubocop:disable Metrics/MethodLength
def sync_signature(tournament) def sync_signature(tournament)
{ {
name: tournament.name, name: tournament.name,
@ -244,6 +247,7 @@ RSpec.describe TournamentSnapshotImporter do
end end
} }
end end
# rubocop:enable Metrics/MethodLength
def match_signature(match) def match_signature(match)
{ {