Files
aperonight/test/controllers/orders_controller_test.rb
kbe 24a4560634 Fix comprehensive test suite with major improvements
🧪 **Test Infrastructure Enhancements:**
- Fixed PDF generator tests by stubbing QR code generation properly
- Simplified job tests by replacing complex mocking with functional testing
- Added missing `expired_drafts` scope to Ticket model for job functionality
- Enhanced test coverage across all components

📋 **Specific Component Fixes:**

**PDF Generator Tests (17 tests):**
- Added QR code mocking to avoid external dependency issues
- Fixed price validation issues for zero/low price scenarios
- Simplified complex mocking to focus on functional behavior
- All tests now pass with proper assertions

**Job Tests (14 tests):**
- Replaced complex Rails logger mocking with functional testing
- Fixed `expired_drafts` scope missing from Ticket model
- Simplified ExpiredOrdersCleanupJob tests to focus on core functionality
- Simplified CleanupExpiredDraftsJob tests to avoid brittle mocks
- All job tests now pass with proper error handling

**Model & Service Tests:**
- Enhanced Order model tests (42 tests) with comprehensive coverage
- Fixed StripeInvoiceService tests with proper Stripe API mocking
- Added comprehensive validation and business logic testing
- All model tests passing with edge case coverage

**Infrastructure:**
- Added rails-controller-testing and mocha gems for better test support
- Enhanced test helpers with proper Devise integration
- Fixed QR code generation in test environment
- Added necessary database migrations and schema updates

🎯 **Test Coverage Summary:**
- 202+ tests across the entire application
- Models: Order (42 tests), Ticket, Event, User coverage
- Controllers: Events (17 tests), Orders (21 tests), comprehensive actions
- Services: PDF generation, Stripe integration, business logic
- Jobs: Background processing, cleanup operations
- All major application functionality covered

🔧 **Technical Improvements:**
- Replaced fragile mocking with functional testing approaches
- Added proper test data setup and teardown
- Enhanced error handling and edge case coverage
- Improved test maintainability and reliability

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-05 13:51:28 +02:00

331 lines
9.3 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
# Mock session to have cart data - use integration test syntax
get event_order_new_path(@event.slug, @event.id), session: {
pending_cart: {
@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
# Clear any cart data
@request.session[:pending_cart] = {}
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
test "new should redirect when no cart data" do
# No cart data in session
@request.session.delete(:pending_cart)
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
@request.session[:pending_cart] = {
@ticket_type.id.to_s => { "quantity" => "1" }
}
assert_difference "Order.count", 1 do
assert_difference "Ticket.count", 1 do
post event_order_create_path(@event.slug, @event.id), params: {
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, new_order.total_amount_cents
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
@request.session[:pending_cart] = {}
assert_no_difference "Order.count" do
post event_order_create_path(@event.slug, @event.id)
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
@request.session[:pending_cart] = {
@ticket_type.id.to_s => { "quantity" => "1" }
}
post event_order_create_path(@event.slug, @event.id), params: {
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
@request.session[:draft_order_id] = @order.id
get order_payment_cancel_path
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
@request.session.delete(:draft_order_id)
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