Billing upgrade/downgrade, inviti in app e diretta YouTube da mobile.

Upgrade Stripe con addebito immediato; downgrade programmato a fine periodo.
UX billing più sobria con box info; icone piani. API inviti e OAuth YouTube
per staff trasmissione; deep link join; scelta partita programmata o nuova.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-02 22:15:27 +02:00
parent 2cb267f991
commit 566104aff4
49 changed files with 1615 additions and 173 deletions

View File

@@ -0,0 +1,54 @@
require "rails_helper"
RSpec.describe "Api::V1::Invitations", type: :request do
let(:club) { Club.create!(name: "FC Test", sport: "volleyball", primary_color: "#e53935", secondary_color: "#ffffff") }
let(:team) { club.teams.create!(name: "Squadra A", sport: "volleyball") }
let(:owner) do
User.create!(email: "owner@test.it", name: "Owner", password: "password123", role: "coach").tap do |u|
ClubMembership.create!(user: u, club: club, role: "owner")
end
end
let(:invitee) { User.create!(email: "streamer@test.it", name: "Streamer", password: "password123", role: "coach") }
let(:token) { TeamInvitation.generate_token }
let!(:invitation) do
team.team_invitations.create!(
email: invitee.email,
token_digest: Digest::SHA256.hexdigest(token),
role: "member",
staff_kind: "transmission",
expires_at: 7.days.from_now
)
end
describe "GET /api/v1/invitations/:token" do
it "mostra anteprima invito valido" do
get "/api/v1/invitations/#{token}"
expect(response).to have_http_status(:ok)
expect(response.parsed_body["email"]).to eq("streamer@test.it")
expect(response.parsed_body["team_name"]).to eq("Squadra A")
end
end
describe "POST /api/v1/invitations/:token/accept" do
it "accetta con email corretta" do
post "/api/v1/auth/login", params: { email: invitee.email, password: "password123" }
access = response.parsed_body["access_token"]
post "/api/v1/invitations/#{token}/accept",
headers: { "Authorization" => "Bearer #{access}" }
expect(response).to have_http_status(:ok)
expect(invitee.user_teams.find_by(team: team)&.staff_kind).to eq("transmission")
end
it "rifiuta email diversa" do
post "/api/v1/auth/login", params: { email: owner.email, password: "password123" }
access = response.parsed_body["access_token"]
post "/api/v1/invitations/#{token}/accept",
headers: { "Authorization" => "Bearer #{access}" }
expect(response).to have_http_status(:unprocessable_entity)
end
end
end