# frozen_string_literal: true require "rails_helper" RSpec.describe Sessions::Start, "one live per user" do let(:user) { User.create!(email: "tx@test.it", name: "Tx", password: "Password123", role: "coach") } let(:club) { Club.create!(name: "Club A", sport: "volleyball") } let(:team) { club.teams.create!(name: "Team A", sport: "volleyball") } let(:match_a) { team.matches.create!(opponent_name: "Opp A", sport: "volleyball") } let(:match_b) { team.matches.create!(opponent_name: "Opp B", sport: "volleyball") } before do club.club_memberships.create!(user: user, role: "owner") plan = Plan.find_or_initialize_by(slug: "premium_full") plan.name ||= "Premium Full" plan.features = (plan.features || {}).merge( "platforms" => %w[matchlivetv youtube], "concurrent_streams_limit" => 10 ) plan.save! club.create_subscription!(plan: plan, status: "active") if club.subscription.blank? allow(SessionChannel).to receive(:broadcast_message) end def session_for(match, status:, device_model: "Pixel 8") StreamSession.create!( match: match, user: user, platform: "matchlivetv", status: status, device_manufacturer: "Google", device_model: device_model, client_os: "android" ) end it "avvia la prima diretta" do session = session_for(match_a, status: "idle") described_class.new(session).call expect(session.reload.status).to eq("connecting") expect(StreamConcurrencyViolation.count).to eq(0) end it "blocca la seconda diretta dello stesso account e registra l'abuso" do live = session_for(match_a, status: "live", device_model: "Pixel 8") live.update!(started_at: 10.minutes.ago) second = session_for(match_b, status: "idle", device_model: "iPhone 15") second.update!(client_os: "ios", device_manufacturer: "Apple") expect { described_class.new(second).call }.to raise_error(Teams::EntitlementError) { |e| expect(e.code).to eq("user_concurrent_stream") } expect(second.reload.status).to eq("idle") violation = StreamConcurrencyViolation.last expect(violation).to be_present expect(violation.user_email).to eq(user.email) expect(violation.occupying_session_id).to eq(live.id) expect(violation.attempted_session_id).to eq(second.id) expect(violation.devices_differ).to be(true) expect(violation.attempt_action).to eq("start") end it "non blocca un secondo account sulla stessa società" do other = User.create!(email: "tx2@test.it", name: "Tx2", password: "Password123", role: "coach") club.club_memberships.create!(user: other, role: "owner") session_for(match_a, status: "live") other_session = StreamSession.create!( match: match_b, user: other, platform: "matchlivetv", status: "idle" ) described_class.new(other_session).call expect(other_session.reload.status).to eq("connecting") end it "considera occupante anche una sessione in pausa" do session_for(match_a, status: "paused") second = session_for(match_b, status: "idle") expect { described_class.new(second).call }.to raise_error(Teams::EntitlementError) { |e| expect(e.code).to eq("user_concurrent_stream") } end it "non considera occupante una sessione idle" do session_for(match_a, status: "idle") second = session_for(match_b, status: "idle") described_class.new(second).call expect(second.reload.status).to eq("connecting") end end