refactor: clean timer api routes
This commit is contained in:
parent
8b17bc0608
commit
13acbad55f
|
|
@ -12,15 +12,15 @@ class TournamentsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
before_action :set_tournament_for_show, only: %i[show]
|
before_action :set_tournament_for_show, only: %i[show]
|
||||||
before_action :set_tournament, only: %i[update destroy set_timer_end timer_end sync_state test_sync]
|
before_action :set_tournament, only: %i[update destroy set_timer timer sync_state test_sync]
|
||||||
before_action :authenticate_user!, only: %i[create update destroy set_timer_end test_sync]
|
before_action :authenticate_user!, only: %i[create update destroy set_timer test_sync]
|
||||||
before_action -> { require_owner! @tournament.owner }, only: %i[update destroy set_timer_end test_sync]
|
before_action -> { require_owner! @tournament.owner }, only: %i[update destroy set_timer test_sync]
|
||||||
before_action :validate_create_params, only: %i[create]
|
before_action :validate_create_params, only: %i[create]
|
||||||
before_action :validate_update_params, only: %i[update]
|
before_action :validate_update_params, only: %i[update]
|
||||||
before_action :validate_set_timer_end_params, only: %i[set_timer_end]
|
before_action :validate_set_timer_params, only: %i[set_timer]
|
||||||
before_action :ensure_update_allowed!, only: %i[update]
|
before_action :ensure_update_allowed!, only: %i[update]
|
||||||
before_action :ensure_destroy_allowed!, only: %i[destroy]
|
before_action :ensure_destroy_allowed!, only: %i[destroy]
|
||||||
before_action :ensure_timer_update_allowed!, only: %i[set_timer_end]
|
before_action :ensure_timer_update_allowed!, only: %i[set_timer]
|
||||||
before_action :authorize_sync_request!, only: %i[sync_state]
|
before_action :authorize_sync_request!, only: %i[sync_state]
|
||||||
rescue_from ActiveRecord::RecordNotFound, with: :render_not_found_error
|
rescue_from ActiveRecord::RecordNotFound, with: :render_not_found_error
|
||||||
|
|
||||||
|
|
@ -129,14 +129,14 @@ class TournamentsController < ApplicationController
|
||||||
@tournament.destroy
|
@tournament.destroy
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /tournaments/:id/timer_end
|
# GET /tournaments/:id/timer
|
||||||
def timer_end
|
def timer
|
||||||
render json: serialize_timer_state(@tournament)
|
render json: serialize_timer_state(@tournament)
|
||||||
end
|
end
|
||||||
|
|
||||||
# PATCH /tournaments/:id/set_timer_end
|
# PATCH /tournaments/:id/timer
|
||||||
def set_timer_end
|
def set_timer
|
||||||
if @tournament.update(timer_end_params)
|
if @tournament.update(timer_params)
|
||||||
push_sync_if_needed!(@tournament)
|
push_sync_if_needed!(@tournament)
|
||||||
render json: @tournament
|
render json: @tournament
|
||||||
else
|
else
|
||||||
|
|
@ -171,9 +171,9 @@ class TournamentsController < ApplicationController
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def timer_end_params
|
def timer_params
|
||||||
{
|
{
|
||||||
timer_end: params[:timer_end] || params[:timestamp],
|
timer_end: params[:timer_end],
|
||||||
timer_mode: params[:timer_mode]
|
timer_mode: params[:timer_mode]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
@ -332,15 +332,12 @@ class TournamentsController < ApplicationController
|
||||||
TournamentSyncEnqueue.call(tournament)
|
TournamentSyncEnqueue.call(tournament)
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_set_timer_end_params
|
def validate_set_timer_params
|
||||||
timestamp = params[:timestamp]
|
timestamp = params[:timestamp]
|
||||||
timestamp_seconds = params[:timestamp_seconds]
|
timestamp_seconds = params[:timestamp_seconds]
|
||||||
timer_mode = params[:timer_mode]
|
timer_mode = params[:timer_mode]
|
||||||
clear_timer = ActiveModel::Type::Boolean.new.cast(params[:clear_timer])
|
clear_timer = ActiveModel::Type::Boolean.new.cast(params[:clear_timer])
|
||||||
|
|
||||||
timestamp = params[:timer_end] if timestamp.blank? && params[:timer_end].present?
|
|
||||||
timestamp_seconds = params[:timer_end_seconds] if timestamp_seconds.blank? && params[:timer_end_seconds].present?
|
|
||||||
|
|
||||||
if clear_timer
|
if clear_timer
|
||||||
if timestamp.present? || timestamp_seconds.present? || timer_mode.present?
|
if timestamp.present? || timestamp_seconds.present? || timer_mode.present?
|
||||||
return render json: { error: 'clear_timer cannot be combined with timestamp values or timer_mode' },
|
return render json: { error: 'clear_timer cannot be combined with timestamp values or timer_mode' },
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ class TournamentSnapshotImporter
|
||||||
def update_tournament!
|
def update_tournament!
|
||||||
root_attrs = snapshot.slice(*ROOT_ATTRIBUTES)
|
root_attrs = snapshot.slice(*ROOT_ATTRIBUTES)
|
||||||
root_attrs[:code] = tournament.code if code_taken_by_another_tournament?(root_attrs[:code])
|
root_attrs[:code] = tournament.code if code_taken_by_another_tournament?(root_attrs[:code])
|
||||||
root_attrs[:timer_end] = parse_time(snapshot[:timestamp] || snapshot[:timer_end])
|
root_attrs[:timer_end] = parse_time(snapshot[:timestamp])
|
||||||
root_attrs[:timer_mode] = snapshot[:timer_mode]
|
root_attrs[:timer_mode] = snapshot[:timer_mode]
|
||||||
root_attrs[:sync_source_tournament_id] = snapshot[:id]
|
root_attrs[:sync_source_tournament_id] = snapshot[:id]
|
||||||
root_attrs[:sync_last_imported_snapshot_at] = snapshot_generated_at
|
root_attrs[:sync_last_imported_snapshot_at] = snapshot_generated_at
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
member do
|
member do
|
||||||
get :timer_end
|
get :timer
|
||||||
patch :set_timer_end
|
patch :timer, action: :set_timer
|
||||||
patch :sync_state
|
patch :sync_state
|
||||||
post :test_sync
|
post :test_sync
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ Timer state is available in normal tournament payload:
|
||||||
|
|
||||||
Dedicated timer endpoint also exists:
|
Dedicated timer endpoint also exists:
|
||||||
|
|
||||||
- `GET /tournaments/:id/timer_end`
|
- `GET /tournaments/:id/timer`
|
||||||
|
|
||||||
Response shape:
|
Response shape:
|
||||||
|
|
||||||
|
|
@ -95,10 +95,7 @@ Follower tournaments in `read_only_mode` reject writes with `423`.
|
||||||
|
|
||||||
Endpoint:
|
Endpoint:
|
||||||
|
|
||||||
- `PATCH /tournaments/:id/set_timer_end`
|
- `PATCH /tournaments/:id/timer`
|
||||||
|
|
||||||
Current route name still says `set_timer_end`.
|
|
||||||
Payload field name is now `timestamp`.
|
|
||||||
|
|
||||||
### Start countdown by duration
|
### Start countdown by duration
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ module TurniereE2E
|
||||||
}
|
}
|
||||||
|
|
||||||
timer_response = patch!(
|
timer_response = patch!(
|
||||||
"/tournaments/#{tournament.fetch(:id)}/set_timer_end",
|
"/tournaments/#{tournament.fetch(:id)}/timer",
|
||||||
body: { timestamp_seconds: 600 }
|
body: { timestamp_seconds: 600 }
|
||||||
)
|
)
|
||||||
checkpoints[:timer_set] = { timestamp: timer_response.fetch(:timestamp) }
|
checkpoints[:timer_set] = { timestamp: timer_response.fetch(:timestamp) }
|
||||||
|
|
|
||||||
|
|
@ -220,12 +220,12 @@ RSpec.describe TournamentsController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #timer_end' do
|
describe 'GET #timer' do
|
||||||
it 'returns timer state in ISO 8601 format' do
|
it 'returns timer state in ISO 8601 format' do
|
||||||
timer_end = Time.utc(2026, 4, 13, 18, 0, 0)
|
timer_end = Time.utc(2026, 4, 13, 18, 0, 0)
|
||||||
@tournament.update!(timer_end: timer_end, timer_mode: 'countdown')
|
@tournament.update!(timer_end: timer_end, timer_mode: 'countdown')
|
||||||
|
|
||||||
get :timer_end, params: { id: @tournament.to_param }
|
get :timer, params: { id: @tournament.to_param }
|
||||||
|
|
||||||
expect(response).to be_successful
|
expect(response).to be_successful
|
||||||
expect(deserialize_response(response)[:timestamp]).to eq(timer_end.iso8601)
|
expect(deserialize_response(response)[:timestamp]).to eq(timer_end.iso8601)
|
||||||
|
|
@ -233,7 +233,7 @@ RSpec.describe TournamentsController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'PATCH #set_timer_end' do
|
describe 'PATCH #set_timer' do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
apply_authentication_headers_for @user
|
apply_authentication_headers_for @user
|
||||||
end
|
end
|
||||||
|
|
@ -241,7 +241,7 @@ RSpec.describe TournamentsController, type: :controller do
|
||||||
it 'stores timezone-aware timestamp values without shifting them' do
|
it 'stores timezone-aware timestamp values without shifting them' do
|
||||||
timestamp = '2030-04-13T18:00:00+02:00'
|
timestamp = '2030-04-13T18:00:00+02:00'
|
||||||
|
|
||||||
patch :set_timer_end, params: { id: @tournament.to_param, timestamp: timestamp }
|
patch :set_timer, params: { id: @tournament.to_param, timestamp: timestamp }
|
||||||
|
|
||||||
expect(response).to be_successful
|
expect(response).to be_successful
|
||||||
expect(@tournament.reload.timer_end.iso8601).to eq(Time.iso8601(timestamp).utc.iso8601)
|
expect(@tournament.reload.timer_end.iso8601).to eq(Time.iso8601(timestamp).utc.iso8601)
|
||||||
|
|
@ -252,7 +252,7 @@ RSpec.describe TournamentsController, type: :controller do
|
||||||
it 'starts countup timer at current time when timer_mode=countup' do
|
it 'starts countup timer at current time when timer_mode=countup' do
|
||||||
before_request = Time.zone.now
|
before_request = Time.zone.now
|
||||||
|
|
||||||
patch :set_timer_end, params: { id: @tournament.to_param, timer_mode: 'countup' }
|
patch :set_timer, params: { id: @tournament.to_param, timer_mode: 'countup' }
|
||||||
|
|
||||||
expect(response).to be_successful
|
expect(response).to be_successful
|
||||||
expect(@tournament.reload.timer_mode).to eq('countup')
|
expect(@tournament.reload.timer_mode).to eq('countup')
|
||||||
|
|
@ -263,7 +263,7 @@ RSpec.describe TournamentsController, type: :controller do
|
||||||
it 'clears timer state when clear_timer=true' do
|
it 'clears timer state when clear_timer=true' do
|
||||||
@tournament.update!(timer_end: Time.utc(2030, 4, 13, 18, 0, 0), timer_mode: 'countdown')
|
@tournament.update!(timer_end: Time.utc(2030, 4, 13, 18, 0, 0), timer_mode: 'countdown')
|
||||||
|
|
||||||
patch :set_timer_end, params: { id: @tournament.to_param, clear_timer: true }
|
patch :set_timer, params: { id: @tournament.to_param, clear_timer: true }
|
||||||
|
|
||||||
expect(response).to be_successful
|
expect(response).to be_successful
|
||||||
expect(@tournament.reload.timer_end).to be_nil
|
expect(@tournament.reload.timer_end).to be_nil
|
||||||
|
|
@ -273,7 +273,7 @@ RSpec.describe TournamentsController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'rejects timestamp_seconds for countup mode' do
|
it 'rejects timestamp_seconds for countup mode' do
|
||||||
patch :set_timer_end, 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_entity)
|
||||||
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')
|
||||||
|
|
@ -742,7 +742,7 @@ RSpec.describe TournamentsController, type: :controller do
|
||||||
playoff_teams_amount: 4,
|
playoff_teams_amount: 4,
|
||||||
instant_finalists_amount: 4,
|
instant_finalists_amount: 4,
|
||||||
intermediate_round_participants_amount: 0,
|
intermediate_round_participants_amount: 0,
|
||||||
timer_end: nil,
|
timestamp: nil,
|
||||||
teams: [{ id: 7, name: 'Alpha' }],
|
teams: [{ id: 7, name: 'Alpha' }],
|
||||||
stages: [],
|
stages: [],
|
||||||
groups: [],
|
groups: [],
|
||||||
|
|
|
||||||
|
|
@ -125,21 +125,21 @@ RSpec.describe 'Backend API surface HTTP E2E' do
|
||||||
forbidden_update = other_client.patch("/tournaments/#{tournament.fetch(:id)}", body: { name: 'Not Allowed' })
|
forbidden_update = other_client.patch("/tournaments/#{tournament.fetch(:id)}", body: { name: 'Not Allowed' })
|
||||||
unauthenticated_update = anonymous_client.patch("/tournaments/#{tournament.fetch(:id)}", body: { name: 'No Auth' })
|
unauthenticated_update = anonymous_client.patch("/tournaments/#{tournament.fetch(:id)}", body: { name: 'No Auth' })
|
||||||
|
|
||||||
timer_seconds = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/set_timer_end", body: { timestamp_seconds: 120 })
|
timer_seconds = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/timer", body: { timestamp_seconds: 120 })
|
||||||
timer_show = anonymous_client.get("/tournaments/#{tournament.fetch(:id)}/timer_end")
|
timer_show = anonymous_client.get("/tournaments/#{tournament.fetch(:id)}/timer")
|
||||||
timer_countup = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/set_timer_end", body: { timer_mode: 'countup' })
|
timer_countup = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/timer", body: { timer_mode: 'countup' })
|
||||||
timer_clear = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/set_timer_end", body: { clear_timer: true })
|
timer_clear = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/timer", body: { clear_timer: true })
|
||||||
timer_double = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/set_timer_end", body: {
|
timer_double = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/timer", body: {
|
||||||
timestamp_seconds: 120,
|
timestamp_seconds: 120,
|
||||||
timestamp: (Time.now.utc + 240).iso8601
|
timestamp: (Time.now.utc + 240).iso8601
|
||||||
})
|
})
|
||||||
timer_invalid_seconds = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/set_timer_end", body: { timestamp_seconds: 'nope' })
|
timer_invalid_seconds = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/timer", body: { timestamp_seconds: 'nope' })
|
||||||
timer_past = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/set_timer_end", body: { timestamp_seconds: 0 })
|
timer_past = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/timer", body: { timestamp_seconds: 0 })
|
||||||
timer_countup_seconds = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/set_timer_end", body: {
|
timer_countup_seconds = owner_client.patch("/tournaments/#{tournament.fetch(:id)}/timer", body: {
|
||||||
timer_mode: 'countup',
|
timer_mode: 'countup',
|
||||||
timestamp_seconds: 60
|
timestamp_seconds: 60
|
||||||
})
|
})
|
||||||
timer_forbidden = other_client.patch("/tournaments/#{tournament.fetch(:id)}/set_timer_end", body: { timestamp_seconds: 60 })
|
timer_forbidden = other_client.patch("/tournaments/#{tournament.fetch(:id)}/timer", body: { timestamp_seconds: 60 })
|
||||||
|
|
||||||
destroy_response = owner_client.delete("/tournaments/#{tournament.fetch(:id)}")
|
destroy_response = owner_client.delete("/tournaments/#{tournament.fetch(:id)}")
|
||||||
after_destroy = anonymous_client.get("/tournaments/#{tournament.fetch(:id)}")
|
after_destroy = anonymous_client.get("/tournaments/#{tournament.fetch(:id)}")
|
||||||
|
|
|
||||||
|
|
@ -41,19 +41,19 @@ RSpec.describe 'Tournament timer follower sync websocket HTTP E2E' do
|
||||||
expect(initial_payload.fetch('timestamp')).to be_nil
|
expect(initial_payload.fetch('timestamp')).to be_nil
|
||||||
expect(initial_payload.fetch('timer_mode')).to be_nil
|
expect(initial_payload.fetch('timer_mode')).to be_nil
|
||||||
|
|
||||||
countdown = source_client.patch("/tournaments/#{source.fetch(:id)}/set_timer_end", body: { timestamp_seconds: 120 })
|
countdown = source_client.patch("/tournaments/#{source.fetch(:id)}/timer", body: { timestamp_seconds: 120 })
|
||||||
expect(countdown[:status]).to eq(200)
|
expect(countdown[:status]).to eq(200)
|
||||||
|
|
||||||
countdown_payload = wait_for_timer_state!(cable_client, timer_mode: 'countdown')
|
countdown_payload = wait_for_timer_state!(cable_client, timer_mode: 'countdown')
|
||||||
expect(countdown_payload.fetch('timestamp')).to eq(countdown.dig(:json, :timestamp))
|
expect(countdown_payload.fetch('timestamp')).to eq(countdown.dig(:json, :timestamp))
|
||||||
|
|
||||||
countup = source_client.patch("/tournaments/#{source.fetch(:id)}/set_timer_end", body: { timer_mode: 'countup' })
|
countup = source_client.patch("/tournaments/#{source.fetch(:id)}/timer", body: { timer_mode: 'countup' })
|
||||||
expect(countup[:status]).to eq(200)
|
expect(countup[:status]).to eq(200)
|
||||||
|
|
||||||
countup_payload = wait_for_timer_state!(cable_client, timer_mode: 'countup')
|
countup_payload = wait_for_timer_state!(cable_client, timer_mode: 'countup')
|
||||||
expect(countup_payload.fetch('timestamp')).to eq(countup.dig(:json, :timestamp))
|
expect(countup_payload.fetch('timestamp')).to eq(countup.dig(:json, :timestamp))
|
||||||
|
|
||||||
clear = source_client.patch("/tournaments/#{source.fetch(:id)}/set_timer_end", body: { clear_timer: true })
|
clear = source_client.patch("/tournaments/#{source.fetch(:id)}/timer", body: { clear_timer: true })
|
||||||
expect(clear[:status]).to eq(200)
|
expect(clear[:status]).to eq(200)
|
||||||
|
|
||||||
cleared_payload = wait_for_timer_state!(cable_client, timer_mode: nil)
|
cleared_payload = wait_for_timer_state!(cable_client, timer_mode: nil)
|
||||||
|
|
|
||||||
|
|
@ -32,19 +32,19 @@ RSpec.describe 'Tournament timer websocket HTTP E2E' do
|
||||||
expect(initial_payload.fetch('timestamp')).to be_nil
|
expect(initial_payload.fetch('timestamp')).to be_nil
|
||||||
expect(initial_payload.fetch('timer_mode')).to be_nil
|
expect(initial_payload.fetch('timer_mode')).to be_nil
|
||||||
|
|
||||||
countdown = client.patch("/tournaments/#{tournament.fetch(:id)}/set_timer_end", body: { timestamp_seconds: 120 })
|
countdown = client.patch("/tournaments/#{tournament.fetch(:id)}/timer", body: { timestamp_seconds: 120 })
|
||||||
expect(countdown[:status]).to eq(200)
|
expect(countdown[:status]).to eq(200)
|
||||||
|
|
||||||
countdown_payload = wait_for_timer_state!(cable_client, timer_mode: 'countdown')
|
countdown_payload = wait_for_timer_state!(cable_client, timer_mode: 'countdown')
|
||||||
expect(countdown_payload.fetch('timestamp')).to eq(countdown.dig(:json, :timestamp))
|
expect(countdown_payload.fetch('timestamp')).to eq(countdown.dig(:json, :timestamp))
|
||||||
|
|
||||||
countup = client.patch("/tournaments/#{tournament.fetch(:id)}/set_timer_end", body: { timer_mode: 'countup' })
|
countup = client.patch("/tournaments/#{tournament.fetch(:id)}/timer", body: { timer_mode: 'countup' })
|
||||||
expect(countup[:status]).to eq(200)
|
expect(countup[:status]).to eq(200)
|
||||||
|
|
||||||
countup_payload = wait_for_timer_state!(cable_client, timer_mode: 'countup')
|
countup_payload = wait_for_timer_state!(cable_client, timer_mode: 'countup')
|
||||||
expect(countup_payload.fetch('timestamp')).to eq(countup.dig(:json, :timestamp))
|
expect(countup_payload.fetch('timestamp')).to eq(countup.dig(:json, :timestamp))
|
||||||
|
|
||||||
clear = client.patch("/tournaments/#{tournament.fetch(:id)}/set_timer_end", body: { clear_timer: true })
|
clear = client.patch("/tournaments/#{tournament.fetch(:id)}/timer", body: { clear_timer: true })
|
||||||
expect(clear[:status]).to eq(200)
|
expect(clear[:status]).to eq(200)
|
||||||
|
|
||||||
cleared_payload = wait_for_timer_state!(cable_client, timer_mode: nil)
|
cleared_payload = wait_for_timer_state!(cable_client, timer_mode: nil)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue