Introduce architettura multi-sport con catalogo, engine scoring e overlay.
Catalogo sport in YAML, board implicito, engine per volley/basket/timed/racket/timer/generic, regia e app Android allineate. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
31
backend/spec/domain/sports/catalog_spec.rb
Normal file
31
backend/spec/domain/sports/catalog_spec.rb
Normal file
@@ -0,0 +1,31 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Sports::Catalog do
|
||||
describe ".find" do
|
||||
it "restituisce pallavolo con board volley" do
|
||||
entry = described_class.find("pallavolo")
|
||||
expect(entry[:board]).to eq("volley")
|
||||
expect(entry[:overlay]).to eq("volley")
|
||||
expect(entry[:default_rules]["sets_to_win"]).to eq(3)
|
||||
end
|
||||
|
||||
it "mappa legacy volleyball" do
|
||||
expect(described_class.normalize_key("volleyball")).to eq("pallavolo")
|
||||
end
|
||||
|
||||
it "altro usa board generic" do
|
||||
entry = described_class.find("altro")
|
||||
expect(entry[:board]).to eq("generic")
|
||||
expect(entry[:overlay]).to eq("none")
|
||||
end
|
||||
end
|
||||
|
||||
describe ".as_api_list" do
|
||||
it "include tutti gli sport configurati" do
|
||||
keys = described_class.as_api_list.map { |e| e[:key] }
|
||||
expect(keys).to include("pallavolo", "basket", "calcio_a_5", "tennis", "ginnastica_artistica", "altro")
|
||||
end
|
||||
end
|
||||
end
|
||||
19
backend/spec/requests/api/v1/sports_spec.rb
Normal file
19
backend/spec/requests/api/v1/sports_spec.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe "Api::V1::Sports", type: :request do
|
||||
let!(:user) { User.create!(email: "s@example.com", password: "secret123", name: "U", role: "coach") }
|
||||
|
||||
it "GET /api/v1/sports restituisce il catalogo" do
|
||||
post "/api/v1/auth/login", params: { email: user.email, password: "secret123" }
|
||||
token = response.parsed_body["access_token"]
|
||||
get "/api/v1/sports", headers: { "Authorization" => "Bearer #{token}" }
|
||||
expect(response).to have_http_status(:ok)
|
||||
body = JSON.parse(response.body)
|
||||
expect(body).to be_an(Array)
|
||||
pallavolo = body.find { |s| s["key"] == "pallavolo" }
|
||||
expect(pallavolo["board"]).to eq("volley")
|
||||
expect(pallavolo["allowed_overlays"]).to include("volley", "timer", "none")
|
||||
end
|
||||
end
|
||||
18
backend/spec/services/scoring/generic_engine_spec.rb
Normal file
18
backend/spec/services/scoring/generic_engine_spec.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Scoring::Engines::GenericEngine do
|
||||
let!(:club) { Club.create!(name: "C", sport: "volleyball", primary_color: "#e53935", secondary_color: "#ffffff") }
|
||||
let!(:team) { club.teams.create!(name: "T", sport: "altro") }
|
||||
let!(:match) { team.matches.create!(opponent_name: "Opp", sport: "altro") }
|
||||
let!(:user) { User.create!(email: "g@example.com", password: "secret123", name: "Coach") }
|
||||
let!(:session) { StreamSession.create!(match: match, user: user, status: "live", platform: "matchlivetv") }
|
||||
|
||||
it "incrementa solo il contatore senza chiudere set" do
|
||||
engine = described_class.new(match: match)
|
||||
result = engine.apply(session: session, action: "home_point")
|
||||
expect(result.score.home_points).to eq(1)
|
||||
expect(result.set_won).to be(false)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user