Add comprehensive unit test coverage for controllers, models, and services

- Translate French comments to English in controllers and tests
- Fix test failures: route helpers, validations, MySQL transaction issues
- Add Timecop for time-dependent tests and update database config for isolation
This commit is contained in:
kbe
2025-09-15 19:27:06 +02:00
parent ee43996a77
commit 4cde466f9a
13 changed files with 287 additions and 29 deletions

View File

@@ -1,5 +1,5 @@
# Contrôleur API pour la gestion des ressources d'événements
# Fournit des points de terminaison RESTful pour les opérations CRUD sur le modèle Event
# API Controller for managing event resources
# Provides RESTful endpoints for CRUD operations on the Event model
module Api
module V1
@@ -7,27 +7,27 @@ module Api
# Skip API key authentication for store_cart action (used by frontend forms)
skip_before_action :authenticate_api_key, only: [ :store_cart ]
# Charge l'évén avant certaines actions pour réduire les duplications
# Loads the event before certain actions to reduce duplications
before_action :set_event, only: [ :show, :update, :destroy, :store_cart ]
# GET /api/v1/events
# Récupère tous les événements triés par date de création (du plus récent au plus ancien)
# Retrieves all events sorted by creation date (most recent first)
def index
@events = Event.all.order(created_at: :desc)
render json: @events, status: :ok
end
# GET /api/v1/events/:id
# Récupère un seul événement par son ID
# Retourne 404 si l'événement n'est pas trouvé
# Retrieves a single event by its ID
# Returns 404 if the event is not found
def show
render json: @event, status: :ok
end
# POST /api/v1/events
# Crée un nouvel événement avec les attributs fournis
# Retourne 201 Created en cas de succès avec les données de l'événement
# Retourne 422 Unprocessable Entity avec les messages d'erreur en cas d'échec
# Creates a new event with the provided attributes
# Returns 201 Created on success with the event data
# Returns 422 Unprocessable Entity with error messages on failure
def create
@event = Event.new(event_params)
if @event.save
@@ -38,9 +38,9 @@ module Api
end
# PATCH/PUT /api/v1/events/:id
# Met à jour un événement existant avec les attributs fournis
# Retourne 200 OK avec les données mises à jour en cas de succès
# Retourne 422 Unprocessable Entity avec les messages d'erreur en cas d'échec
# Updates an existing event with the provided attributes
# Returns 200 OK with updated data on success
# Returns 422 Unprocessable Entity with error messages on failure
def update
if @event.update(event_params)
render json: @event, status: :ok
@@ -50,8 +50,8 @@ module Api
end
# DELETE /api/v1/events/:id
# Supprime définitivement un événement
# Retourne 204 No Content en cas de succès
# Permanently deletes an event
# Returns 204 No Content on success
def destroy
@event.destroy
head :no_content
@@ -66,33 +66,37 @@ module Api
render json: { status: "success", message: "Cart stored successfully" }
rescue => e
error_message = e.message.present? ? e.message : "Erreur inconnue"
error_message = e.message.present? ? e.message : "Unknown error"
Rails.logger.error "Error storing cart: #{error_message}"
render json: { status: "error", message: "Failed to store cart" }, status: 500
end
private
# Trouve un événement par son ID ou retourne 404 Introuvable
# Utilisé comme before_action pour les actions show, update et destroy
# Finds an event by its ID or returns 404 Not Found
# Used as before_action for the show, update, and destroy actions
def set_event
@event = Event.find(params[:id])
rescue ActiveRecord::RecordNotFound
render json: { error: "Événement non trouvé" }, status: :not_found
render json: { error: "Event not found" }, status: :not_found
end
# Paramètres forts pour la création et la mise à jour des événements
# Liste blanche des attributs autorisés pour éviter les vulnérabilités de mass assignment
# Strong parameters for creating and updating events
# Whitelist of allowed attributes to avoid mass assignment vulnerabilities
def event_params
params.require(:event).permit(
:name,
:slug,
:description,
:state,
:venue_name,
:venue_address,
:start_time,
:end_time,
:latitude,
:longitude,
:featured
:featured,
:user_id
)
end
end

View File

@@ -38,8 +38,6 @@ class ApplicationController < ActionController::Base
# Skip for API endpoints
controller_name.start_with?("api/") ||
# Skip for health checks
controller_name == "rails/health" ||
# Skip for home page (when not signed in)
(controller_name == "pages" && action_name == "home")
controller_name == "rails/health"
end
end

View File

@@ -107,10 +107,7 @@
</div>
<h3 class="text-2xl font-bold text-gray-900 mb-4">Aucun événement disponible</h3>
<p class="text-gray-600 mb-8 max-w-md mx-auto">Il n'y a aucun événement à venir pour le moment. Revenez bientôt pour découvrir de nouvelles sorties!</p>
<%= link_to "Retour à l'accueil", root_path, class: "inline-flex items-center bg-purple-600 text-white px-6 py-3 rounded-full font-semibold hover:bg-purple-700 transition-all duration-200 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" do %>
<i data-lucide="home" class="w-4 h-4 mr-2"></i>
Retour à l'accueil
<% end %>
<%= link_to "<i data-lucide=\"home\" class=\"w-4 h-4 mr-2\"></i> Retour à l'accueil".html_safe, root_path, class: "inline-flex items-center bg-purple-600 text-white px-6 py-3 rounded-full font-semibold hover:bg-purple-700 transition-all duration-200 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" %>
</div>
<% end %>
</div>