Files
aperonight/test/controllers/orders_controller_test.rb
kbe 67d3bcde5b Fix service fee missing from Stripe invoices
The StripeInvoiceService was only creating line items for tickets but missing
the 1€ service fee, causing a discrepancy where customers paid 26€ via Stripe
checkout but the generated invoice only showed 25€.

- Add service fee line item to Stripe invoices in StripeInvoiceService
- Update all related tests to expect two line items (tickets + service fee)
- Fix order controller test to account for service fee in total calculation

Now Stripe invoices properly match the amount paid: tickets + 1€ service fee.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-08 11:15:36 +02:00

313 lines
9.1 KiB
Ruby

require "test_helper"
class OrdersControllerTest < ActionDispatch::IntegrationTest
def setup
@user = User.create!(
email: "test@example.com",
password: "password123",
password_confirmation: "password123"
)
@event = Event.create!(
name: "Test Event",
slug: "test-event",
description: "A valid description for the test event that is long enough",
latitude: 48.8566,
longitude: 2.3522,
venue_name: "Test Venue",
venue_address: "123 Test Street",
user: @user,
start_time: 1.week.from_now,
end_time: 1.week.from_now + 3.hours,
state: :published
)
@ticket_type = TicketType.create!(
name: "General Admission",
description: "General admission tickets with full access to the event",
price_cents: 2500,
quantity: 100,
sale_start_at: Time.current,
sale_end_at: @event.start_time - 1.hour,
requires_id: false,
event: @event
)
@order = Order.create!(
user: @user,
event: @event,
status: "draft",
total_amount_cents: 2500
)
@ticket = Ticket.create!(
order: @order,
ticket_type: @ticket_type,
status: "draft",
first_name: "John",
last_name: "Doe"
)
sign_in @user
end
# === Authentication Tests ===
test "should require authentication for all actions" do
sign_out @user
get event_order_new_path(@event.slug, @event.id)
assert_redirected_to new_user_session_path
post event_order_create_path(@event.slug, @event.id)
assert_redirected_to new_user_session_path
get order_path(@order)
assert_redirected_to new_user_session_path
get checkout_order_path(@order)
assert_redirected_to new_user_session_path
end
# === New Action Tests ===
test "should get new with valid event" do
# Pass cart data as parameter for testing
get event_order_new_path(@event.slug, @event.id), params: {
cart_data: { @ticket_type.id.to_s => { "quantity" => "2" } }
}
assert_response :success
# Should assign tickets_needing_names
tickets_needing_names = assigns(:tickets_needing_names)
assert_not_nil tickets_needing_names
assert_equal 2, tickets_needing_names.size
assert_equal @ticket_type.id, tickets_needing_names.first[:ticket_type_id]
end
test "new should redirect when cart is empty" do
# Pass empty cart data as parameter
get event_order_new_path(@event.slug, @event.id), params: { cart_data: {} }
assert_redirected_to event_path(@event.slug, @event)
assert_match /sélectionner vos billets/, flash[:alert]
end
test "new should redirect when no cart data" do
# No cart data passed as parameter
get event_order_new_path(@event.slug, @event.id)
assert_redirected_to event_path(@event.slug, @event)
assert_match /sélectionner vos billets/, flash[:alert]
end
# === Create Action Tests ===
test "should create order with valid ticket data" do
assert_difference "Order.count", 1 do
assert_difference "Ticket.count", 1 do
post event_order_create_path(@event.slug, @event.id), params: {
cart_data: { @ticket_type.id.to_s => { "quantity" => "1" } },
tickets_attributes: {
"0" => {
ticket_type_id: @ticket_type.id,
first_name: "Jane",
last_name: "Smith"
}
}
}
end
end
new_order = Order.last
assert_equal "draft", new_order.status
assert_equal @user, new_order.user
assert_equal @event, new_order.event
assert_equal @ticket_type.price_cents + 100, new_order.total_amount_cents # includes 1€ service fee
assert_redirected_to checkout_order_path(new_order)
assert_equal new_order.id, session[:draft_order_id]
assert_nil session[:pending_cart]
end
test "create should redirect when cart is empty" do
assert_no_difference "Order.count" do
post event_order_create_path(@event.slug, @event.id), params: { cart_data: {} }
end
assert_redirected_to event_path(@event.slug, @event)
assert_match /Aucun billet sélectionné/, flash[:alert]
end
test "create should handle missing ticket names" do
post event_order_create_path(@event.slug, @event.id), params: {
cart_data: { @ticket_type.id.to_s => { "quantity" => "1" } },
tickets_attributes: {
"0" => {
ticket_type_id: @ticket_type.id,
first_name: "",
last_name: ""
}
}
}
# Should redirect back to new order page
assert_redirected_to event_order_new_path(@event.slug, @event.id)
assert_match /Aucun billet valide créé/, flash[:alert]
end
# === Show Action Tests ===
test "should show order" do
get order_path(@order)
assert_response :success
order = assigns(:order)
assert_equal @order, order
tickets = assigns(:tickets)
assert_includes tickets, @ticket
end
test "should not show other user's order" do
other_user = User.create!(
email: "other@example.com",
password: "password123",
password_confirmation: "password123"
)
other_order = Order.create!(
user: other_user,
event: @event,
status: "draft",
total_amount_cents: 2500
)
get order_path(other_order)
# Should redirect to dashboard/root with alert
assert_redirected_to root_path
assert_match /Commande non trouvée/, flash[:alert]
end
# === Checkout Action Tests ===
test "should show checkout page" do
get checkout_order_path(@order)
assert_response :success
order = assigns(:order)
assert_equal @order, order
tickets = assigns(:tickets)
assert_includes tickets, @ticket
total_amount = assigns(:total_amount)
assert_equal @order.total_amount_cents, total_amount
expiring_soon = assigns(:expiring_soon)
assert_not_nil expiring_soon
end
test "checkout should redirect expired order" do
# Make order expired
@order.update!(expires_at: 1.hour.ago)
get checkout_order_path(@order)
assert_redirected_to event_path(@event.slug, @event)
assert_match /commande a expiré/, flash[:alert]
@order.reload
assert_equal "expired", @order.status
end
# === Retry Payment Tests ===
test "should allow retry payment for retryable order" do
post retry_payment_order_path(@order)
assert_redirected_to checkout_order_path(@order)
end
test "should not allow retry payment for non-retryable order" do
# Make order non-retryable (too many attempts)
@order.update!(payment_attempts: Order::MAX_PAYMENT_ATTEMPTS)
post retry_payment_order_path(@order)
assert_redirected_to event_path(@event.slug, @event)
assert_match /ne peut plus être payée/, flash[:alert]
end
# === Increment Payment Attempt Tests ===
test "should increment payment attempt via AJAX" do
initial_attempts = @order.payment_attempts
post increment_payment_attempt_order_path(@order), xhr: true
assert_response :success
response_data = JSON.parse(@response.body)
assert response_data["success"]
assert_equal initial_attempts + 1, response_data["attempts"]
@order.reload
assert_equal initial_attempts + 1, @order.payment_attempts
assert_not_nil @order.last_payment_attempt_at
end
# === Payment Success Tests (simplified) ===
test "payment_success should redirect when Stripe not configured" do
# Mock the config to return nil
Rails.application.config.stripe = { secret_key: nil }
get order_payment_success_path, params: { session_id: "test_session" }
assert_redirected_to root_path
assert_match /système de paiement n'est pas correctement configuré/, flash[:alert]
end
# === Payment Cancel Tests ===
test "payment_cancel should redirect to checkout if order can retry" do
get order_payment_cancel_path, params: { order_id: @order.id }
assert_redirected_to checkout_order_path(@order)
assert_match /paiement a été annulé.*réessayer/, flash[:alert]
end
test "payment_cancel should redirect to root if no order in session" do
get order_payment_cancel_path
assert_redirected_to root_path
assert_match /paiement a été annulé/, flash[:alert]
end
# === Error Handling Tests ===
test "should handle non-existent event in new" do
get event_order_new_path(@event.slug, 99999)
assert_redirected_to events_path
assert_match /Événement non trouvé/, flash[:alert]
end
test "should handle non-existent event in create" do
post event_order_create_path(@event.slug, 99999)
assert_redirected_to events_path
assert_match /Événement non trouvé/, flash[:alert]
end
test "should handle non-existent order" do
get order_path(99999)
assert_redirected_to root_path
assert_match /Commande non trouvée/, flash[:alert]
end
# === Route Helper Tests ===
test "should have correct route helpers" do
# Test that the route helpers exist and work
assert_not_nil event_order_new_path(@event.slug, @event.id)
assert_not_nil event_order_create_path(@event.slug, @event.id)
assert_not_nil order_path(@order)
assert_not_nil checkout_order_path(@order)
assert_not_nil retry_payment_order_path(@order)
assert_not_nil increment_payment_attempt_order_path(@order)
end
end