require "test_helper" class Promoter::PayoutsControllerTest < ActionDispatch::IntegrationTest setup do @user = users(:one) @event = events(:concert_event) @payout = payouts(:one) end test "should get index" do sign_in @user # Make the user a promoter @user.update(is_professionnal: true) get promoter_payouts_url assert_response :success end test "should get show" do sign_in @user # Make the user a promoter @user.update(is_professionnal: true) # Create a payout that belongs to the user payout = Payout.create!( user: @user, event: @event, amount_cents: 1000, fee_cents: 100 ) get promoter_payout_url(payout) assert_response :success end test "should create payout" do sign_in @user # Make the user a promoter @user.update(is_professionnal: true) # Make the user the owner of the event @event.update(user: @user) # Make the event end in the past @event.update(end_time: 1.day.ago) # Create some earnings for the event @event.earnings.create!( user: @user, order: orders(:paid_order), amount_cents: 1000, fee_cents: 100, status: :pending ) assert_difference("Payout.count", 1) do post promoter_payouts_url, params: { event_id: @event.id } end assert_redirected_to promoter_payout_path(Payout.last) end # Comprehensive index test with data test "index shows completed payouts, eligible events, and totals for promoter" do sign_in @user @user.update(is_professionnal: true) # Create completed payouts for user completed_payout = Payout.create!(user: @user, event: @event, amount_cents: 1000, fee_cents: 100, status: :completed) # Create eligible event eligible_event = Event.create!(name: "Eligible Event", slug: "eligible-event", description: "desc", venue_name: "v", venue_address: "a", latitude: 48.0, longitude: 2.0, start_time: 1.day.ago, end_time: 2.days.ago, user: @user, state: :published) # Setup net >0 for eligible earning = Earning.create!(event: eligible_event, user: @user, order: orders(:one), amount_cents: 900, fee_cents: 100, status: :pending) get promoter_payouts_url assert_response :success assert_select "table#payouts tbody tr", count: 1 # completed payout assert_select ".eligible-events li", count: 1 # eligible event assert_match /Pending net earnings: €9.00/, @response.body # totals assert_match /Total paid out: €10.00/, @response.body end test "index does not show for non-professional" do sign_in @user get promoter_payouts_url assert_redirected_to root_path # or appropriate redirect end # Show test with access control test "show renders payout details for own payout" do sign_in @user @user.update(is_professionnal: true) payout = Payout.create!(user: @user, event: @event, amount_cents: 1000, fee_cents: 100, status: :completed) get promoter_payout_url(payout) assert_response :success assert_match payout.amount.to_s, @response.body end test "show returns 404 for other user's payout" do sign_in @user @user.update(is_professionnal: true) other_user = User.create!(email: "other@example.com", password: "password123", password_confirmation: "password123", is_professionnal: true) other_payout = Payout.create!(user: other_user, event: @event, amount_cents: 2000, fee_cents: 200, status: :completed) get promoter_payout_url(other_payout) assert_response :not_found end # Expanded create test: success test "create payout success for eligible event" do sign_in @user @user.update(is_professionnal: true) @event.update(user: @user, end_time: 1.day.ago) # ended # Setup net >0 earning = @event.earnings.create!(user: @user, order: orders(:paid_order), amount_cents: 900, fee_cents: 100, status: :pending) # Ensure eligible assert @event.can_request_payout?(@user) assert_difference("Payout.count", 1) do post promoter_payouts_url, params: { event_id: @event.id } end assert_redirected_to promoter_payout_path(Payout.last) assert_flash :notice, /Payout requested successfully/ assert_equal :requested, @event.reload.payout_status # assume enum payout = Payout.last assert_equal @event.total_gross_cents, payout.amount_cents assert_equal @event.total_fees_cents, payout.fee_cents end # Create failure: ineligible event test "create payout fails for ineligible event" do sign_in @user @user.update(is_professionnal: true) @event.update(user: @user, end_time: 1.day.from_now) # not ended assert_not @event.can_request_payout?(@user) assert_no_difference("Payout.count") do post promoter_payouts_url, params: { event_id: @event.id } end assert_redirected_to event_path(@event) assert_flash :alert, /Event not eligible for payout/ end test "show renders manual payout details correctly" do sign_in @user @user.update(is_professionnal: true) payout = Payout.create!(user: @user, event: @event, amount_cents: 1000, fee_cents: 100, status: :completed, stripe_payout_id: "MANUAL_abc123") get promoter_payout_url(payout) assert_response :success assert_match "Manual Payout ID", @response.body assert_match "Manual Transfer", @response.body end # Create failure: validation errors test "create payout fails with validation errors" do sign_in @user @user.update(is_professionnal: true) @event.update(user: @user, end_time: 1.day.ago) # Setup net =0 assert_not @event.can_request_payout?(@user) assert_no_difference("Payout.count") do post promoter_payouts_url, params: { event_id: @event.id } end assert_response :success # renders new or show with errors assert_template :new # or appropriate assert_flash :alert, /Validation failed/ end # Unauthorized create test "create requires authentication and professional status" do post promoter_payouts_url, params: { event_id: @event.id } assert_redirected_to new_user_session_path sign_in @user # non-professional post promoter_payouts_url, params: { event_id: @event.id } assert_redirected_to root_path # or deny access end end