require "test_helper" require "stripe" class PayoutServiceTest < ActiveSupport::TestCase setup do @user = users(:one) @event = events(:concert_event) @payout = Payout.create!(user: @user, event: @event, amount_cents: 9000, fee_cents: 1000) Stripe.api_key = "test_key" end test "process! success creates transfer and updates status" do # Mock Stripe Transfer Stripe::Transfer.expects(:create).with( amount: 90, # cents to euros currency: "eur", destination: @user.stripe_connected_account_id, description: "Payout for event #{@event.name}" ).returns(stub(id: "tr_123", status: "succeeded")) @payout.update(status: :pending) service = PayoutService.new(@payout) service.process! @payout.reload assert_equal :completed, @payout.status assert_equal "tr_123", @payout.stripe_payout_id assert @payout.earnings.update_all(status: :paid) # assume update_earnings_status end test "process! failure with Stripe error sets status to failed" do Stripe::Transfer.expects(:create).raises(Stripe::CardError.new("Insufficient funds")) @payout.update(status: :pending) service = PayoutService.new(@payout) assert_raises Stripe::CardError do service.process! end @payout.reload assert_equal :failed, @payout.status assert_not_nil @payout.error_message # assume logged end test "process! idempotent for already completed" do @payout.update(status: :completed, stripe_payout_id: "tr_456") Stripe::Transfer.expects(:create).never service = PayoutService.new(@payout) service.process! @payout.reload assert_equal :completed, @payout.status end test "update_earnings_status marks earnings as paid" do earning1 = Earning.create!(event: @event, user: @user, order: orders(:one), amount_cents: 4500, fee_cents: 500, status: :pending) earning2 = Earning.create!(event: @event, user: @user, order: orders(:two), amount_cents: 4500, fee_cents: 500, status: :pending) @payout.earnings << earning1 @payout.earnings << earning2 service = PayoutService.new(@payout) service.update_earnings_status(:paid) assert_equal :paid, earning1.reload.status assert_equal :paid, earning2.reload.status end end