274 lines
9.2 KiB
Go
274 lines
9.2 KiB
Go
package tests
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"gestion/handlers"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func alertContext(username, role string, body []byte, alertID int) (*gin.Context, *httptest.ResponseRecorder) {
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/livreur/alert", bytes.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
rec := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(rec)
|
|
c.Request = req
|
|
c.Set("database", testDB)
|
|
if username != "" {
|
|
c.Set("username", username)
|
|
}
|
|
c.Set("role", role)
|
|
if alertID != 0 {
|
|
c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", alertID)}}
|
|
}
|
|
return c, rec
|
|
}
|
|
|
|
func createTestAlert(t *testing.T, username, message string) int {
|
|
t.Helper()
|
|
alert, err := testDB.CreateAlert(username, message)
|
|
if err != nil {
|
|
t.Fatalf("CreateAlert: %v", err)
|
|
}
|
|
t.Cleanup(func() {
|
|
testDB.GDB.Exec(`DELETE FROM alerte_policy WHERE id = ?`, alert.ID)
|
|
})
|
|
return alert.ID
|
|
}
|
|
|
|
// ── AlertPolice ──────────────────────────────────────────────────────────────
|
|
|
|
func TestAlertPolice_LivreurCreatesAlert(t *testing.T) {
|
|
livreur := testUserPrefix + "alert_create_livreur"
|
|
body, _ := json.Marshal(map[string]string{"message": "Contrôle en cours"})
|
|
c, rec := alertContext(livreur, "livreur", body, 0)
|
|
handlers.AlertPolice(c)
|
|
t.Cleanup(func() { testDB.GDB.Exec(`DELETE FROM alerte_policy WHERE username = ?`, livreur) })
|
|
|
|
if rec.Code != http.StatusCreated {
|
|
t.Fatalf("status HTTP: got=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
|
|
var resp struct {
|
|
AlertID int `json:"alert_id"`
|
|
User string `json:"user"`
|
|
}
|
|
json.Unmarshal(rec.Body.Bytes(), &resp)
|
|
if resp.User != livreur {
|
|
t.Errorf("user: got=%q want=%q", resp.User, livreur)
|
|
}
|
|
|
|
alert, err := testDB.GetAlertPolicy(resp.AlertID)
|
|
if err != nil {
|
|
t.Fatalf("GetAlertPolicy: %v", err)
|
|
}
|
|
if alert.Message != "Contrôle en cours" || alert.Status != "true" {
|
|
t.Errorf("alerte créée: message=%q status=%q", alert.Message, alert.Status)
|
|
}
|
|
}
|
|
|
|
func TestAlertPolice_NonLivreurForbidden(t *testing.T) {
|
|
for _, role := range []string{"client", "admin", "cabine"} {
|
|
t.Run(role, func(t *testing.T) {
|
|
body, _ := json.Marshal(map[string]string{"message": "test"})
|
|
c, rec := alertContext(testUserPrefix+"alert_forbidden_"+role, role, body, 0)
|
|
handlers.AlertPolice(c)
|
|
if rec.Code != http.StatusForbidden {
|
|
t.Errorf("le rôle %q ne doit pas pouvoir déclencher une alerte police: got=%d", role, rec.Code)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// ── GetAlert ─────────────────────────────────────────────────────────────────
|
|
|
|
func TestGetAlert_LivreurCanViewOwnAlert(t *testing.T) {
|
|
livreur := testUserPrefix + "alert_view_own"
|
|
alertID := createTestAlert(t, livreur, "test")
|
|
|
|
c, rec := alertContext(livreur, "livreur", nil, alertID)
|
|
handlers.GetAlert(c)
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("status HTTP: got=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestGetAlert_LivreurCannotViewOthersAlert(t *testing.T) {
|
|
owner := testUserPrefix + "alert_view_owner"
|
|
intruder := testUserPrefix + "alert_view_intruder"
|
|
alertID := createTestAlert(t, owner, "test")
|
|
|
|
c, rec := alertContext(intruder, "livreur", nil, alertID)
|
|
handlers.GetAlert(c)
|
|
if rec.Code != http.StatusForbidden {
|
|
t.Fatalf("un livreur ne doit pas pouvoir consulter l'alerte d'un autre: got=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestGetAlert_AdminCanViewAnyAlert(t *testing.T) {
|
|
owner := testUserPrefix + "alert_view_admin_owner"
|
|
alertID := createTestAlert(t, owner, "test")
|
|
|
|
c, rec := alertContext(testUserPrefix+"alert_view_admin", "admin", nil, alertID)
|
|
handlers.GetAlert(c)
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("un admin doit pouvoir consulter n'importe quelle alerte: got=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
}
|
|
|
|
// ── EndAlert ─────────────────────────────────────────────────────────────────
|
|
|
|
func TestEndAlert_OwnerCanEnd(t *testing.T) {
|
|
livreur := testUserPrefix + "alert_end_owner"
|
|
alertID := createTestAlert(t, livreur, "test")
|
|
|
|
c, rec := alertContext(livreur, "livreur", nil, alertID)
|
|
handlers.EndAlert(c)
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("status HTTP: got=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
|
|
alert, _ := testDB.GetAlertPolicy(alertID)
|
|
if alert.Status != "false" {
|
|
t.Errorf("statut après EndAlert: got=%q want=false", alert.Status)
|
|
}
|
|
}
|
|
|
|
func TestEndAlert_NonOwnerLivreurRejected(t *testing.T) {
|
|
owner := testUserPrefix + "alert_end_owner2"
|
|
intruder := testUserPrefix + "alert_end_intruder"
|
|
alertID := createTestAlert(t, owner, "test")
|
|
|
|
c, rec := alertContext(intruder, "livreur", nil, alertID)
|
|
handlers.EndAlert(c)
|
|
if rec.Code != http.StatusForbidden {
|
|
t.Fatalf("un livreur tiers ne doit pas pouvoir terminer l'alerte d'un autre: got=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
|
|
alert, _ := testDB.GetAlertPolicy(alertID)
|
|
if alert.Status != "true" {
|
|
t.Errorf("l'alerte ne doit pas être terminée par un intrus: got=%q want=true", alert.Status)
|
|
}
|
|
}
|
|
|
|
// ── DeleteAlert ──────────────────────────────────────────────────────────────
|
|
//
|
|
// Corrigé : un livreur ne peut supprimer que ses propres alertes (comme
|
|
// EndAlert) ; un admin garde l'accès complet sans restriction de propriétaire.
|
|
|
|
func TestDeleteAlert_OwnerLivreurCanDeleteOwnAlert(t *testing.T) {
|
|
owner := testUserPrefix + "alert_delete_owner_ok"
|
|
alertID := createTestAlert(t, owner, "test")
|
|
|
|
c, rec := alertContext(owner, "livreur", nil, alertID)
|
|
handlers.DeleteAlert(c)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("le propriétaire doit pouvoir supprimer sa propre alerte: got=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
if _, err := testDB.GetAlertPolicy(alertID); err == nil {
|
|
t.Error("l'alerte doit être supprimée")
|
|
}
|
|
}
|
|
|
|
func TestDeleteAlert_NonOwnerLivreurRejected(t *testing.T) {
|
|
owner := testUserPrefix + "alert_delete_owner"
|
|
intruder := testUserPrefix + "alert_delete_intruder"
|
|
alertID := createTestAlert(t, owner, "test")
|
|
|
|
c, rec := alertContext(intruder, "livreur", nil, alertID)
|
|
handlers.DeleteAlert(c)
|
|
|
|
if rec.Code != http.StatusForbidden {
|
|
t.Fatalf("un livreur tiers ne doit pas pouvoir supprimer l'alerte d'un autre: got=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
if _, err := testDB.GetAlertPolicy(alertID); err != nil {
|
|
t.Error("l'alerte ne doit pas être supprimée par un intrus")
|
|
}
|
|
}
|
|
|
|
func TestDeleteAlert_AdminCanDeleteAnyAlertRegardlessOfOwner(t *testing.T) {
|
|
owner := testUserPrefix + "alert_delete_admin_owner"
|
|
alertID := createTestAlert(t, owner, "test")
|
|
|
|
c, rec := alertContext(testUserPrefix+"alert_delete_admin", "admin", nil, alertID)
|
|
handlers.DeleteAlert(c)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("un admin doit pouvoir supprimer n'importe quelle alerte: got=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
if _, err := testDB.GetAlertPolicy(alertID); err == nil {
|
|
t.Error("l'alerte doit être supprimée par l'admin")
|
|
}
|
|
}
|
|
|
|
func TestDeleteAlert_NonLivreurNonAdminForbidden(t *testing.T) {
|
|
owner := testUserPrefix + "alert_delete_forbidden_owner"
|
|
alertID := createTestAlert(t, owner, "test")
|
|
|
|
c, rec := alertContext(testUserPrefix+"alert_delete_forbidden_cabine", "cabine", nil, alertID)
|
|
handlers.DeleteAlert(c)
|
|
if rec.Code != http.StatusForbidden {
|
|
t.Errorf("le rôle cabine ne doit pas pouvoir supprimer une alerte: got=%d", rec.Code)
|
|
}
|
|
}
|
|
|
|
// ── Listing ──────────────────────────────────────────────────────────────────
|
|
|
|
func TestGetMyAlerts_ReturnsOnlyOwnAlerts(t *testing.T) {
|
|
mine := testUserPrefix + "alert_mine"
|
|
other := testUserPrefix + "alert_other"
|
|
createTestAlert(t, mine, "à moi 1")
|
|
createTestAlert(t, mine, "à moi 2")
|
|
createTestAlert(t, other, "pas à moi")
|
|
|
|
c, rec := alertContext(mine, "livreur", nil, 0)
|
|
handlers.GetMyAlerts(c)
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("status HTTP: got=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
|
|
var resp struct {
|
|
Count int `json:"count"`
|
|
}
|
|
json.Unmarshal(rec.Body.Bytes(), &resp)
|
|
if resp.Count != 2 {
|
|
t.Errorf("nombre d'alertes du livreur: got=%d want=2", resp.Count)
|
|
}
|
|
}
|
|
|
|
func TestGetActiveAlerts_ExcludesEndedAlerts(t *testing.T) {
|
|
livreur := testUserPrefix + "alert_active_filter"
|
|
activeID := createTestAlert(t, livreur, "active")
|
|
endedID := createTestAlert(t, livreur, "terminée")
|
|
if err := testDB.EndAlert(endedID); err != nil {
|
|
t.Fatalf("EndAlert (setup): %v", err)
|
|
}
|
|
|
|
alerts, err := testDB.GetActiveAlerts()
|
|
if err != nil {
|
|
t.Fatalf("GetActiveAlerts: %v", err)
|
|
}
|
|
var foundActive, foundEnded bool
|
|
for _, a := range alerts {
|
|
if a.ID == activeID {
|
|
foundActive = true
|
|
}
|
|
if a.ID == endedID {
|
|
foundEnded = true
|
|
}
|
|
}
|
|
if !foundActive {
|
|
t.Error("l'alerte active doit apparaître dans GetActiveAlerts")
|
|
}
|
|
if foundEnded {
|
|
t.Error("l'alerte terminée ne doit pas apparaître dans GetActiveAlerts")
|
|
}
|
|
}
|