Files
aperonight/test/models/event_test.rb
kbe 4ca8d73c8e feat: Add comprehensive test coverage for Event model
- Add tests for SEO-friendly slug generation with name, venue, and city
- Add tests for slug uniqueness and fallback behavior
- Add tests for image URL validation and handling
- Add tests for image detection methods (has_image?, display_image)
- Fix duplicate has_image? method in Event model
- Remove duplicate test method to resolve test failures
- All 50 tests now passing

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-01 08:48:03 +02:00

474 lines
20 KiB
Ruby
Executable File

require "test_helper"
require "timecop"
class EventTest < ActiveSupport::TestCase
# Test that Event model exists
test "should be a class" do
assert_kind_of Class, Event
end
# Test validations
test "should not save event without name" do
event = Event.new(description: "Test event description")
assert_not event.save
end
test "should not save event without description" do
event = Event.new(name: "Test Event")
assert_not event.save
end
test "should not save event with name less than 3 characters" do
event = Event.new(name: "AB", description: "Valid description for the event")
assert_not event.save
end
test "should not save event with description less than 10 characters" do
event = Event.new(name: "Valid Event Name", description: "Too short")
assert_not event.save
end
test "should not save event without latitude" do
event = Event.new(
name: "Valid Event Name",
description: "Valid description for the event that is long enough",
longitude: 2.3522
)
assert_not event.save
end
test "should not save event without longitude" do
event = Event.new(
name: "Valid Event Name",
description: "Valid description for the event that is long enough",
latitude: 48.8566
)
assert_not event.save
end
test "should not save event with invalid latitude" do
event = Event.new(
name: "Valid Event Name",
description: "Valid description for the event that is long enough",
latitude: 95.0,
longitude: 2.3522,
venue_name: "Test Venue",
venue_address: "123 Test Street"
)
assert_not event.save
end
test "should not save event with invalid longitude" do
event = Event.new(
name: "Valid Event Name",
description: "Valid description for the event that is long enough",
latitude: 48.8566,
longitude: 190.0,
venue_name: "Test Venue",
venue_address: "123 Test Street"
)
assert_not event.save
end
test "should not save event without slug" do
event = Event.new(
name: "Valid Event Name",
description: "Valid description for the event that is long enough",
latitude: 48.8566,
longitude: 2.3522,
venue_name: "Test Venue",
venue_address: "123 Test Street"
)
assert_not event.save
end
test "should not save event with slug less than 3 characters" do
event = Event.new(
name: "Valid Event Name",
description: "Valid description for the event that is long enough",
latitude: 48.8566,
longitude: 2.3522,
venue_name: "Test Venue",
venue_address: "123 Test Street",
slug: "ab"
)
assert_not event.save
end
test "should save valid event" do
user = User.create!(
email: "test@example.com",
password: "password123",
password_confirmation: "password123"
)
event = Event.new(
name: "Valid Event Name",
slug: "valid-event-name",
description: "Valid description for the event that is long enough",
latitude: 48.8566,
longitude: 2.3522,
venue_name: "Test Venue",
venue_address: "123 Test Street",
user: user,
)
assert event.save
end
# Test enum states
test "should have valid states" do
assert_equal %w[draft published canceled sold_out], Event.states.keys
end
test "should default to draft state" do
event = Event.new(
name: "Valid Event Name",
description: "Valid description for the event that is long enough",
latitude: 48.8566,
longitude: 2.3522,
venue_name: "Test Venue",
venue_address: "123 Test Street"
)
assert_equal "draft", event.state
end
# Test associations
test "should belong to user" do
association = Event.reflect_on_association(:user)
assert_equal :belongs_to, association.macro
end
test "should have many ticket_types" do
association = Event.reflect_on_association(:ticket_types)
assert_equal :has_many, association.macro
end
test "should have many tickets through ticket_types" do
association = Event.reflect_on_association(:tickets)
assert_equal :has_many, association.macro
assert_equal :ticket_types, association.options[:through]
end
# Test scopes
test "should respond to featured scope" do
assert_respond_to Event, :featured
end
test "should respond to published scope" do
assert_respond_to Event, :published
end
test "should respond to search_by_name scope" do
assert_respond_to Event, :search_by_name
end
test "upcoming scope should return only published future events" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
future_published = Event.create!(name: "Future", slug: "future", description: "Valid description for the event", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.day.from_now, state: :published)
past_published = Event.create!(name: "Past", slug: "past", description: "Valid description for the event", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.day.ago, state: :published)
future_draft = Event.create!(name: "Draft", slug: "draft", description: "Valid description for the event", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.day.from_now, state: :draft)
upcoming = Event.upcoming
assert_includes upcoming, future_published
assert_not_includes upcoming, past_published
assert_not_includes upcoming, future_draft
end
test "geocoding_successful? should return true for valid coordinates" do
event = Event.new(latitude: 48.8566, longitude: 2.3522, name: "Test", slug: "test", description: "A description that is sufficiently long", venue_name: "v", venue_address: "a")
assert event.geocoding_successful?
end
test "geocoding_successful? should return false for fallback coordinates" do
event = Event.new(latitude: 46.603354, longitude: 1.888334, name: "Test", slug: "test", description: "Valid description for the event", venue_name: "v", venue_address: "a")
assert_not event.geocoding_successful?
end
test "geocoding_status_message should return message when not successful" do
event = Event.new(latitude: 46.603354, longitude: 1.888334, name: "Test", slug: "test", description: "Valid description for the event", venue_name: "v", venue_address: "a")
assert_match(/coordonnées/, event.geocoding_status_message)
end
test "geocoding_status_message should return nil when successful" do
event = Event.new(latitude: 48.8566, longitude: 2.3522, name: "Test", slug: "test", description: "Valid description for the event", venue_name: "v", venue_address: "a")
assert_nil event.geocoding_status_message
end
test "booking_allowed? should be true for published future event" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.create!(name: "Test", slug: "test", description: "A description that is sufficiently long", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.day.from_now, state: :published)
assert event.booking_allowed?
end
test "booking_allowed? should be false for draft event" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.create!(name: "Test", slug: "test", description: "Valid description for the event", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.day.from_now, state: :draft)
assert_not event.booking_allowed?
end
test "booking_allowed? should be false for canceled event" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.create!(name: "Test", slug: "test", description: "Valid description for the event", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.day.from_now, state: :canceled)
assert_not event.booking_allowed?
end
test "booking_allowed? should be false for sold_out event" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.create!(name: "Test", slug: "test", description: "A description that is sufficiently long", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.day.from_now, state: :sold_out)
assert_not event.booking_allowed?
end
test "booking_allowed? should be false during event without allow_booking_during_event" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.create!(name: "Test", slug: "test", description: "Valid description for the event", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.hour.ago, end_time: 2.hours.from_now, state: :published, allow_booking_during_event: false)
assert_not event.booking_allowed?
end
test "booking_allowed? should be true during event with allow_booking_during_event" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.create!(name: "Test", slug: "test", description: "Valid description for the event", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.hour.ago, end_time: 2.hours.from_now, state: :published, allow_booking_during_event: true)
assert event.booking_allowed?
end
test "event_started? should be true after start_time" do
Timecop.freeze(1.hour.from_now) do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.create!(name: "Test", slug: "test", description: "A description that is sufficiently long", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.hour.ago)
assert event.event_started?
end
end
test "event_started? should be false before start_time" do
Timecop.freeze(1.hour.ago) do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.create!(name: "Test", slug: "test", description: "Valid description for the event", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.hour.from_now)
assert_not event.event_started?
end
end
test "event_ended? should be true after end_time" do
Timecop.freeze(1.hour.from_now) do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.create!(name: "Test", slug: "test", description: "Valid description for the event", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.hour.ago, end_time: 30.minutes.ago)
assert event.event_ended?
end
end
test "event_ended? should be false before end_time" do
Timecop.freeze(1.hour.ago) do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.create!(name: "Test", slug: "test", description: "A description that is sufficiently long", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.hour.ago, end_time: 1.hour.from_now)
assert_not event.event_ended?
end
end
test "allow_booking_during_event? should return true when set to true" do
event = Event.new(allow_booking_during_event: true)
assert event.allow_booking_during_event?
end
test "allow_booking_during_event? should return false when nil" do
event = Event.new
assert_not event.allow_booking_during_event?
end
test "should duplicate event with ticket types" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.create!(name: "Original Event", slug: "original", description: "A description that is sufficiently long", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.week.from_now, state: :published)
# Create ticket types
ticket_type1 = TicketType.create!(name: "Standard", description: "A standard ticket for the event", price_cents: 2000, quantity: 100, sale_start_at: 1.day.ago, sale_end_at: event.start_time - 1.hour, event: event)
ticket_type2 = TicketType.create!(name: "VIP", description: "A VIP ticket for the event", price_cents: 5000, quantity: 50, sale_start_at: 1.day.ago, sale_end_at: event.start_time - 1.hour, event: event)
# Duplicate the event
duplicated_event = event.duplicate
# Check that duplication was successful
assert_not_nil duplicated_event
assert_equal "Copie de #{event.name}", duplicated_event.name
assert_equal "draft", duplicated_event.state
assert_equal event.venue_name, duplicated_event.venue_name
assert_equal event.venue_address, duplicated_event.venue_address
# Check that ticket types were duplicated
assert_equal 2, duplicated_event.ticket_types.count
assert_equal "Standard", duplicated_event.ticket_types.find_by(name: "Standard").name
assert_equal "VIP", duplicated_event.ticket_types.find_by(name: "VIP").name
end
test "should duplicate event without ticket types" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.create!(name: "Original Event", slug: "original", description: "A description that is sufficiently long", venue_name: "v", venue_address: "a", user: user, latitude: 48.0, longitude: 2.0, start_time: 1.week.from_now, state: :published)
# Create ticket types
ticket_type1 = TicketType.create!(name: "Standard", description: "A standard ticket for the event", price_cents: 2000, quantity: 100, sale_start_at: 1.day.ago, sale_end_at: event.start_time - 1.hour, event: event)
ticket_type2 = TicketType.create!(name: "VIP", description: "A VIP ticket for the event", price_cents: 5000, quantity: 50, sale_start_at: 1.day.ago, sale_end_at: event.start_time - 1.hour, event: event)
# Duplicate the event without ticket types
duplicated_event = event.duplicate(clone_ticket_types: false)
# Check that duplication was successful
assert_not_nil duplicated_event
assert_equal "Copie de #{event.name}", duplicated_event.name
assert_equal "draft", duplicated_event.state
assert_equal event.venue_name, duplicated_event.venue_name
assert_equal event.venue_address, duplicated_event.venue_address
# Check that ticket types were NOT duplicated
assert_equal 0, duplicated_event.ticket_types.count
end
# Test slug generation functionality
test "should generate slug from name and venue" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.new(
name: "Soirée d'ouverture",
description: "Valid description for the event that is long enough",
venue_name: "Test Venue",
venue_address: "123 Test Street",
user: user,
latitude: 48.0,
longitude: 2.0
)
event.save
assert_equal "soiree-d-ouverture-test-venue", event.slug
end
test "should generate slug from name, venue, and city" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.new(
name: "Fête de la Musique",
venue_name: "Théâtre Principal",
venue_address: "15 Rue de la Paix, 75002 Paris",
description: "Valid description for the event that is long enough",
user: user,
latitude: 48.0,
longitude: 2.0
)
event.save
assert_equal "fete-de-la-musique-theatre-principal-paris", event.slug
end
test "should generate fallback slug when no data available" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.new(
description: "Valid description for the event that is long enough",
venue_address: "123 Test Street",
user: user,
latitude: 48.0,
longitude: 2.0
)
event.save
assert_match /^event-\d+$/, event.slug
end
test "should ensure slug uniqueness" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
# Create first event
event1 = Event.create!(
name: "Test Event",
venue_name: "Venue",
venue_address: "123 Test Street",
description: "Valid description for the event that is long enough",
user: user,
latitude: 48.0,
longitude: 2.0
)
# Create second event with same details
event2 = Event.create!(
name: "Test Event",
venue_name: "Venue",
venue_address: "123 Test Street",
description: "Valid description for the event that is long enough",
user: user,
latitude: 48.0,
longitude: 2.0
)
assert_not_equal event1.slug, event2.slug
assert_match /^test-event-venue-1$/, event2.slug
end
test "should extract city from French postal code" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.new(
name: "Concert",
venue_address: "5 Avenue des Champs-Élysées, 75008 Paris",
description: "Valid description for the event that is long enough",
user: user,
latitude: 48.0,
longitude: 2.0
)
event.save
assert event.slug.include?("paris")
end
# Test image URL functionality
test "should accept valid image URL" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.new(
name: "Event with URL Image",
slug: "event-url-image",
description: "Valid description for the event that is long enough",
venue_name: "Venue",
venue_address: "123 Test Street",
user: user,
latitude: 48.0,
longitude: 2.0,
image_url: "https://example.com/image.jpg"
)
assert event.valid?
end
test "should reject invalid image URL" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.new(
name: "Event with Invalid URL",
slug: "event-invalid-url",
description: "Valid description for the event that is long enough",
venue_name: "Venue",
venue_address: "123 Test Street",
user: user,
latitude: 48.0,
longitude: 2.0,
image_url: "not-a-valid-url"
)
assert_not event.valid?
assert_includes event.errors[:image_url], "doit être une URL valide vers une image (JPG, PNG, GIF, WebP)"
end
test "should reject URL with non-image extension" do
user = User.create!(email: "test@example.com", password: "password123", password_confirmation: "password123")
event = Event.new(
name: "Event with Non-image URL",
slug: "event-non-image-url",
description: "Valid description for the event that is long enough",
venue_name: "Venue",
venue_address: "123 Test Street",
user: user,
latitude: 48.0,
longitude: 2.0,
image_url: "https://example.com/document.pdf"
)
assert_not event.valid?
assert_includes event.errors[:image_url], "doit être une URL valide vers une image (JPG, PNG, GIF, WebP)"
end
test "has_image? should return true for URL image" do
event = Event.new(image_url: "https://example.com/image.jpg")
assert event.has_image?
end
test "has_image? should return false without image" do
event = Event.new
assert_not event.has_image?
end
test "display_image should return image URL when no attached image" do
event = Event.new(image_url: "https://example.com/image.jpg")
assert_equal "https://example.com/image.jpg", event.display_image
end
end