Files
Xor290 22a8d5026c
Frontend Admin - EAS Build / build (push) Canceled after 0s
Frontend Client - EAS Build / build (push) Canceled after 0s
Backend - Build & Lint / build (push) Failing after 25m18s
Frontend Web - Build & Lint / build (push) Failing after 9m58s
chore: build
2026-08-06 12:06:05 +02:00

138 lines
5.1 KiB
Go

package tests
import (
"encoding/json"
"gestion/handlers"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/gin-gonic/gin"
)
// newTestDeliveredOrder crée une commande livrée/approuvée assignée à un
// livreur avec une date de mise à jour contrôlée (GetMyDeliveryStats groupe
// par updated_at, pas created_at).
func newTestDeliveredOrder(t *testing.T, livreurUsername, clientUsername, status string, productID int, quantite, prix, referralUsed float64, updatedAt time.Time) {
t.Helper()
var cmdID int
if err := testDB.GDB.Raw(
`INSERT INTO commandes (username, status, livreur_assign, adresse, total_prix, referral_used, created_at, updated_at)
VALUES (?, ?, ?, 'Adresse test', ?, ?, ?, ?) RETURNING id`,
clientUsername, status, livreurUsername, prix, referralUsed, updatedAt, updatedAt,
).Scan(&cmdID).Error; err != nil {
t.Fatalf("création commande livrée test: %v", err)
}
if err := testDB.GDB.Exec(
`INSERT INTO command_items (command_id, product_id, produit, quantite, prix, status)
VALUES (?, ?, 'item test', ?, ?, 'delivered')`,
cmdID, productID, quantite, prix,
).Error; err != nil {
t.Fatalf("création item commande livrée test: %v", err)
}
}
func livreurStatsContext(username string) (*gin.Context, *httptest.ResponseRecorder) {
req := httptest.NewRequest(http.MethodGet, "/api/v1/livreur/stats", nil)
rec := httptest.NewRecorder()
c, _ := gin.CreateTestContext(rec)
c.Request = req
c.Set("database", testDB)
c.Set("username", username)
c.Set("role", "livreur")
return c, rec
}
type deliveryStatsResponse struct {
Success bool `json:"success"`
TodayCount int `json:"today_count"`
TodayRevenue float64 `json:"today_revenue"`
}
// today_count/today_revenue ne doivent compter que les livraisons du jour
// courant (livre/approved), nettes du crédit de parrainage — pas les jours
// précédents, même récents (voir by_day/by_week qui eux les agrègent).
func TestGetMyDeliveryStats_TodayCountAndRevenue(t *testing.T) {
cleanupStockTestData(t)
livreurUsername := newTestClient(t, "stats_livreur_today")
clientUsername := newTestClient(t, "stats_livreur_today_client")
productID := newTestProduct(t, "StatsLivreurToday", 100)
now := time.Now()
yesterday := now.AddDate(0, 0, -1)
newTestDeliveredOrder(t, livreurUsername, clientUsername, "approved", productID, 2, 40, 10, now) // net 30, aujourd'hui
newTestDeliveredOrder(t, livreurUsername, clientUsername, "approved", productID, 1, 25, 0, yesterday) // hier, ne doit pas compter dans "today"
c, rec := livreurStatsContext(livreurUsername)
handlers.GetMyDeliveryStats(c)
if rec.Code != http.StatusOK {
t.Fatalf("status HTTP: got=%d body=%s", rec.Code, rec.Body.String())
}
var resp deliveryStatsResponse
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
t.Fatalf("décodage réponse: %v body=%s", err, rec.Body.String())
}
if !resp.Success {
t.Fatalf("success=false, body=%s", rec.Body.String())
}
if resp.TodayCount != 1 {
t.Errorf("today_count: got=%d want=1 (la commande d'hier ne doit pas compter)", resp.TodayCount)
}
if resp.TodayRevenue != 30 {
t.Errorf("today_revenue: got=%.2f want=30 (40 - 10 de parrainage)", resp.TodayRevenue)
}
}
// Aucune livraison aujourd'hui : today_count/today_revenue doivent être 0,
// pas une absence de champ (voir le bug initial où le seul indicateur de
// "livraisons du jour" était l'absence de ligne dans by_day).
func TestGetMyDeliveryStats_TodayCountZeroWhenNoDeliveryToday(t *testing.T) {
cleanupStockTestData(t)
livreurUsername := newTestClient(t, "stats_livreur_none")
c, rec := livreurStatsContext(livreurUsername)
handlers.GetMyDeliveryStats(c)
if rec.Code != http.StatusOK {
t.Fatalf("status HTTP: got=%d body=%s", rec.Code, rec.Body.String())
}
var resp deliveryStatsResponse
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
t.Fatalf("décodage réponse: %v body=%s", err, rec.Body.String())
}
if resp.TodayCount != 0 {
t.Errorf("today_count: got=%d want=0", resp.TodayCount)
}
if resp.TodayRevenue != 0 {
t.Errorf("today_revenue: got=%.2f want=0", resp.TodayRevenue)
}
}
// Seules les commandes assignées à CE livreur doivent être comptées.
func TestGetMyDeliveryStats_OnlyCountsOwnDeliveries(t *testing.T) {
cleanupStockTestData(t)
livreurA := newTestClient(t, "stats_livreur_a")
livreurB := newTestClient(t, "stats_livreur_b")
client := newTestClient(t, "stats_livreur_shared_client")
productID := newTestProduct(t, "StatsLivreurIsolation", 100)
now := time.Now()
newTestDeliveredOrder(t, livreurA, client, "approved", productID, 1, 20, 0, now)
newTestDeliveredOrder(t, livreurB, client, "approved", productID, 1, 999, 0, now)
c, rec := livreurStatsContext(livreurA)
handlers.GetMyDeliveryStats(c)
var resp deliveryStatsResponse
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
t.Fatalf("décodage réponse: %v", err)
}
if resp.TodayCount != 1 || resp.TodayRevenue != 20 {
t.Errorf("stats livreur A ne doivent refléter que ses propres livraisons: got count=%d revenue=%.2f want count=1 revenue=20", resp.TodayCount, resp.TodayRevenue)
}
}