263 lines
11 KiB
Ruby
263 lines
11 KiB
Ruby
require "rails_helper"
|
|
|
|
RSpec.describe "Public regia", type: :request do
|
|
let!(:user) { User.create!(email: "regia@test.it", name: "U", password: "Password123", role: "coach") }
|
|
let!(:club) { Club.create!(name: "C", sport: "volleyball", primary_color: "#e53935", secondary_color: "#ffffff") }
|
|
let!(:team) { club.teams.create!(name: "T", sport: "volleyball") }
|
|
let!(:match) { team.matches.create!(opponent_name: "Opp", sport: "volleyball") }
|
|
let!(:session) { StreamSession.create!(match: match, user: user, platform: "matchlivetv", status: "live") }
|
|
|
|
it "mostra la pagina regia con token valido" do
|
|
token = Sessions::RegiaAccess.new(session).issue_token!
|
|
get public_regia_path(token)
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.body).to include("Condividi diretta")
|
|
expect(response.body).to include("Copia live")
|
|
expect(response.body).to include("Condividi link regia")
|
|
expect(response.body).to include("Copia regia")
|
|
expect(response.body).to include(">Diretta<")
|
|
expect(response.body).to include(">Regia<")
|
|
expect(response.body).to include("regia-tool-group")
|
|
expect(response.body).to include("Nascondi anteprima")
|
|
expect(response.body).to include('id="btn-pause"')
|
|
expect(response.body).to include('id="btn-stop"')
|
|
expect(response.body).to include("Qualità minima di trasmissione")
|
|
expect(response.body).to include('id="tel-bitrate"')
|
|
expect(response.body).to include('aria-controls="regia-quality"')
|
|
expect(response.body).to include("/live/#{session.id}")
|
|
expect(response.body).not_to include("Aruba")
|
|
end
|
|
|
|
it "aggiorna il punteggio via API" do
|
|
token = Sessions::RegiaAccess.new(session).issue_token!
|
|
session.create_score_state!(home_sets: 0, away_sets: 0, home_points: 0, away_points: 0, current_set: 1)
|
|
patch public_regia_score_path(token), params: { cmd: "home_point" }
|
|
expect(response).to have_http_status(:ok)
|
|
expect(session.score_state.reload.home_points).to eq(1)
|
|
end
|
|
|
|
it "aggiorna il punteggio basket via API senza errore 500" do
|
|
basket_team = club.teams.create!(name: "U13 Basket", sport_key: "basket")
|
|
basket_match = basket_team.matches.create!(
|
|
opponent_name: "Avversario",
|
|
sport: "basket",
|
|
scoring_rules: { "periods" => 4, "period_duration_secs" => 600, "overtime_duration_secs" => 300 }
|
|
)
|
|
basket_session = StreamSession.create!(match: basket_match, user: user, platform: "matchlivetv", status: "live")
|
|
basket_session.create_score_state!(
|
|
board_type: "basket",
|
|
home_sets: 0,
|
|
away_sets: 0,
|
|
home_points: 0,
|
|
away_points: 0,
|
|
current_set: 1,
|
|
data: {
|
|
"period" => 1,
|
|
"clock_secs" => 600,
|
|
"clock_running" => false,
|
|
"home_score" => 0,
|
|
"away_score" => 0,
|
|
"overtime" => false
|
|
}
|
|
)
|
|
token = Sessions::RegiaAccess.new(basket_session).issue_token!
|
|
|
|
patch public_regia_score_path(token), params: { cmd: "home_point" }, as: :json
|
|
expect(response).to have_http_status(:ok)
|
|
body = response.parsed_body
|
|
expect(body.dig("score", "home_points")).to eq(1)
|
|
expect(body["points_target"]).to eq(0)
|
|
|
|
get public_regia_status_path(token)
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.parsed_body.dig("score", "board_type")).to eq("basket")
|
|
end
|
|
|
|
it "avanza il quarto basket via API" do
|
|
basket_team = club.teams.create!(name: "U13 Basket", sport_key: "basket")
|
|
basket_match = basket_team.matches.create!(opponent_name: "Avversario", sport: "basket")
|
|
basket_session = StreamSession.create!(match: basket_match, user: user, platform: "matchlivetv", status: "live")
|
|
basket_session.create_score_state!(
|
|
board_type: "basket",
|
|
home_sets: 0,
|
|
away_sets: 0,
|
|
home_points: 0,
|
|
away_points: 0,
|
|
current_set: 1,
|
|
data: {
|
|
"period" => 1,
|
|
"clock_secs" => 600,
|
|
"clock_running" => false,
|
|
"home_score" => 0,
|
|
"away_score" => 4,
|
|
"overtime" => false
|
|
}
|
|
)
|
|
token = Sessions::RegiaAccess.new(basket_session).issue_token!
|
|
|
|
patch public_regia_score_path(token), params: { cmd: "advance_period" }, as: :json
|
|
expect(response).to have_http_status(:ok)
|
|
body = response.parsed_body
|
|
expect(body.dig("score", "period")).to eq("Q2")
|
|
expect(body.dig("score", "data", "period")).to eq(2)
|
|
expect(basket_session.score_state.reload.data["period"]).to eq(2)
|
|
end
|
|
|
|
it "avanza il quarto basket anche con periodo Q1 corrotto in data" do
|
|
basket_team = club.teams.create!(name: "U13 Basket", sport_key: "basket")
|
|
basket_match = basket_team.matches.create!(opponent_name: "Avversario", sport: "basket")
|
|
basket_session = StreamSession.create!(match: basket_match, user: user, platform: "matchlivetv", status: "live")
|
|
basket_session.create_score_state!(
|
|
board_type: "basket",
|
|
data: {
|
|
"period" => "Q1",
|
|
"home_score" => 0,
|
|
"away_score" => 4,
|
|
"clock_secs" => 600,
|
|
"clock_running" => false,
|
|
"overtime" => false
|
|
}
|
|
)
|
|
token = Sessions::RegiaAccess.new(basket_session).issue_token!
|
|
|
|
patch public_regia_score_path(token), params: { cmd: "advance_period" }, as: :json
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.parsed_body.dig("score", "period")).to eq("Q2")
|
|
end
|
|
|
|
it "non mostra controlli cronometro sulla regia basket" do
|
|
basket_team = club.teams.create!(name: "U13 Basket", sport_key: "basket")
|
|
basket_match = basket_team.matches.create!(opponent_name: "Avversario", sport: "basket")
|
|
basket_session = StreamSession.create!(match: basket_match, user: user, platform: "matchlivetv", status: "live")
|
|
basket_session.create_score_state!(board_type: "basket", data: { "period" => 1, "home_score" => 0, "away_score" => 0 })
|
|
token = Sessions::RegiaAccess.new(basket_session).issue_token!
|
|
|
|
get public_regia_path(token)
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.body).to include("Prossimo quarto")
|
|
expect(response.body).not_to include("cronometro")
|
|
expect(response.body).not_to include("Cronometro:")
|
|
end
|
|
|
|
it "mette in pausa e riprende la diretta" do
|
|
mtx = instance_double(
|
|
Mediamtx::Client,
|
|
set_always_available: true,
|
|
set_path_recording: true,
|
|
delete_path: true,
|
|
list_paths: [],
|
|
ensure_path_with_slate!: true,
|
|
disable_recording_if_active!: true
|
|
)
|
|
allow(Mediamtx::Client).to receive(:new).and_return(mtx)
|
|
allow(Mediamtx::Client).to receive(:for_session).and_return(mtx)
|
|
allow(Mediamtx::PublisherSync).to receive(:remember_recording_off!)
|
|
|
|
token = Sessions::RegiaAccess.new(session).issue_token!
|
|
post public_regia_pause_path(token)
|
|
expect(response).to have_http_status(:ok)
|
|
expect(session.reload.status).to eq("paused")
|
|
|
|
post public_regia_resume_path(token)
|
|
expect(response).to have_http_status(:ok)
|
|
expect(session.reload.status).to eq("connecting")
|
|
end
|
|
|
|
it "silenzia e riattiva l'audio della diretta" do
|
|
token = Sessions::RegiaAccess.new(session).issue_token!
|
|
expect(session.audio_muted).to eq(false)
|
|
|
|
post public_regia_audio_mute_path(token), params: { muted: true }, as: :json
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.parsed_body["audio_muted"]).to eq(true)
|
|
expect(session.reload.audio_muted).to eq(true)
|
|
|
|
post public_regia_audio_mute_path(token), params: { muted: false }, as: :json
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.parsed_body["audio_muted"]).to eq(false)
|
|
expect(session.reload.audio_muted).to eq(false)
|
|
end
|
|
|
|
it "mostra il pulsante mute sulla pagina regia" do
|
|
token = Sessions::RegiaAccess.new(session).issue_token!
|
|
get public_regia_path(token)
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.body).to include("Silenzia audio")
|
|
expect(response.body).to include("btn-audio-mute")
|
|
end
|
|
|
|
it "emette token valido anche oltre le 8 ore dalla partenza" do
|
|
session.update!(started_at: 9.hours.ago)
|
|
token = Sessions::RegiaAccess.new(session).issue_token!
|
|
session.reload
|
|
expect(session.regia_token_expires_at).to be > Time.current
|
|
get public_regia_path(token)
|
|
expect(response).to have_http_status(:ok)
|
|
end
|
|
|
|
it "aggiorna la qualità minima di trasmissione" do
|
|
token = Sessions::RegiaAccess.new(session).issue_token!
|
|
patch public_regia_min_quality_path(token), params: { min_quality_preset: "720p_30_1.5mbps" }
|
|
expect(response).to have_http_status(:ok)
|
|
expect(session.reload.min_quality_preset).to eq("720p_30_1.5mbps")
|
|
json = JSON.parse(response.body)
|
|
expect(json["min_quality_preset"]).to eq("720p_30_1.5mbps")
|
|
end
|
|
|
|
it "espone la telemetria della camera nello status" do
|
|
session.device_states.create!(
|
|
device_role: "camera",
|
|
battery_level: 81,
|
|
network_type: "WiFi",
|
|
current_bitrate: 2_400_000,
|
|
target_bitrate: 4_500_000,
|
|
fps: 30,
|
|
thermal_state: "nominal",
|
|
last_seen_at: Time.current
|
|
)
|
|
token = Sessions::RegiaAccess.new(session).issue_token!
|
|
get public_regia_path(token)
|
|
expect(response.body).to include('id="regia-telemetry"')
|
|
|
|
get public_regia_status_path(token)
|
|
expect(response).to have_http_status(:ok)
|
|
tel = response.parsed_body["telemetry"]
|
|
expect(tel["battery"]).to eq(81)
|
|
expect(tel["network"]).to eq("WiFi")
|
|
expect(tel["fps"]).to eq(30)
|
|
expect(tel["bitrate"]).to eq(2_400_000)
|
|
expect(tel["thermal_state"]).to eq("nominal")
|
|
expect(tel).to have_key("publisher_online")
|
|
end
|
|
|
|
it "legge publisher_online dal MediaMTX del nodo assegnato" do
|
|
node = StreamNode.create!(
|
|
slug: "ingest-regia-cloud",
|
|
hostname: "ingest-regia-cloud.mltv-stream.net",
|
|
role: "cloud",
|
|
status: "ready",
|
|
provider: "hetzner",
|
|
rtmp_base_url: "rtmp://ingest-regia-cloud.mltv-stream.net:1935",
|
|
hls_base_url: "http://localhost:3000/hls",
|
|
api_base_url: "http://203.0.113.9:9997",
|
|
internal_hls_url: "http://203.0.113.9:8888",
|
|
max_publishers: 4,
|
|
max_relays: 4
|
|
)
|
|
session.update!(stream_node: node)
|
|
home_client = instance_double(Mediamtx::Client, list_paths: [])
|
|
cloud_client = instance_double(
|
|
Mediamtx::Client,
|
|
list_paths: [{ "name" => session.mediamtx_path_name, "online" => true, "ready" => true }]
|
|
)
|
|
allow(Mediamtx::Client).to receive(:new).and_call_original
|
|
allow(Mediamtx::Client).to receive(:new).with(hash_including(base_url: MatchLiveTv.mediamtx_api_url)).and_return(home_client)
|
|
allow(Mediamtx::Client).to receive(:new).with(hash_including(base_url: "http://203.0.113.9:9997")).and_return(cloud_client)
|
|
|
|
token = Sessions::RegiaAccess.new(session).issue_token!
|
|
get public_regia_status_path(token)
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.parsed_body["publisher_online"]).to eq(true)
|
|
end
|
|
end
|