This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"gestion/models"
|
"gestion/models"
|
||||||
"gestion/utils"
|
"gestion/utils"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *Database) CheckAddress(addressByUser *models.Command) error {
|
func (d *Database) CheckAddress(addressByUser *models.Command) error {
|
||||||
@@ -25,7 +26,7 @@ func (d *Database) CheckAddress(addressByUser *models.Command) error {
|
|||||||
}
|
}
|
||||||
normalizedInput := utils.NormalizeAddress(addressByUser.DeliveryAddress)
|
normalizedInput := utils.NormalizeAddress(addressByUser.DeliveryAddress)
|
||||||
for _, c := range corrections {
|
for _, c := range corrections {
|
||||||
if utils.NormalizeAddress(c.InvalidAddress) == normalizedInput {
|
if strings.EqualFold(utils.NormalizeAddress(c.InvalidAddress), normalizedInput) {
|
||||||
addressByUser.DeliveryAddress = c.CorrectAddress
|
addressByUser.DeliveryAddress = c.CorrectAddress
|
||||||
return fmt.Errorf("adresse invalide %s", c.CorrectAddress)
|
return fmt.Errorf("adresse invalide %s", c.CorrectAddress)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,124 @@ func TestCheckAddress_MatchSubstitutesCorrectAddressAndReturnsError(t *testing.T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addCorrectionForFallback enregistre une correction et retourne une fonction
|
||||||
|
// de nettoyage à appeler via t.Cleanup par l'appelant (évite de dépendre de
|
||||||
|
// l'ordre d'exécution entre plusieurs corrections ajoutées dans un même test).
|
||||||
|
func addCorrectionForFallback(t *testing.T, invalid, correct string) {
|
||||||
|
t.Helper()
|
||||||
|
if err := testDB.AddAddress(correct, invalid); err != nil {
|
||||||
|
t.Fatalf("AddAddress(%q -> %q): %v", invalid, correct, err)
|
||||||
|
}
|
||||||
|
var id int64
|
||||||
|
testDB.GDB.Raw(`SELECT id FROM adresse_correction WHERE invalid_address = ?`, invalid).Scan(&id)
|
||||||
|
cleanupAddressCorrections(t, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Les quatre tests suivants couvrent le fallback normalisé de CheckAddress
|
||||||
|
// (utils.NormalizeAddress + strings.EqualFold) : une correction enregistrée
|
||||||
|
// par l'admin avec un texte exact donné doit continuer à s'appliquer même si
|
||||||
|
// le client tape une variante mineure (casse, accents, espaces), plutôt que
|
||||||
|
// d'échouer silencieusement et laisser passer une adresse non livrable.
|
||||||
|
|
||||||
|
func TestCheckAddress_NormalizedFallback_CaseVariantMatches(t *testing.T) {
|
||||||
|
invalid := testUserPrefix + "12 Rue Crebillon Nantes"
|
||||||
|
correct := testUserPrefix + "12 Rue Crébillon, 44000 Nantes"
|
||||||
|
addCorrectionForFallback(t, invalid, correct)
|
||||||
|
|
||||||
|
cmd := &models.Command{DeliveryAddress: testUserPrefix + "12 RUE CREBILLON NANTES"}
|
||||||
|
err := testDB.CheckAddress(cmd)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("attendu une erreur signalant la correction (variante de casse)")
|
||||||
|
}
|
||||||
|
if cmd.DeliveryAddress != correct {
|
||||||
|
t.Errorf("adresse corrigée: got=%q want=%q", cmd.DeliveryAddress, correct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCheckAddress_NormalizedFallback_AccentVariantMatches(t *testing.T) {
|
||||||
|
invalid := testUserPrefix + "10 Rue du Général Buat Nantes"
|
||||||
|
correct := testUserPrefix + "10 Rue du Général Buat, 44000 Nantes"
|
||||||
|
addCorrectionForFallback(t, invalid, correct)
|
||||||
|
|
||||||
|
// Saisie sans accent par le client, alors que la correction enregistrée
|
||||||
|
// par l'admin en contient un.
|
||||||
|
cmd := &models.Command{DeliveryAddress: testUserPrefix + "10 Rue du General Buat Nantes"}
|
||||||
|
err := testDB.CheckAddress(cmd)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("attendu une erreur signalant la correction (variante d'accent)")
|
||||||
|
}
|
||||||
|
if cmd.DeliveryAddress != correct {
|
||||||
|
t.Errorf("adresse corrigée: got=%q want=%q", cmd.DeliveryAddress, correct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCheckAddress_NormalizedFallback_WhitespaceVariantMatches(t *testing.T) {
|
||||||
|
invalid := testUserPrefix + "5 Cours des 50 Otages Nantes"
|
||||||
|
correct := testUserPrefix + "5 Cours des 50 Otages, 44000 Nantes"
|
||||||
|
addCorrectionForFallback(t, invalid, correct)
|
||||||
|
|
||||||
|
cmd := &models.Command{DeliveryAddress: testUserPrefix + "5 Cours des 50 Otages Nantes "}
|
||||||
|
err := testDB.CheckAddress(cmd)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("attendu une erreur signalant la correction (espaces multiples)")
|
||||||
|
}
|
||||||
|
if cmd.DeliveryAddress != correct {
|
||||||
|
t.Errorf("adresse corrigée: got=%q want=%q", cmd.DeliveryAddress, correct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCheckAddress_NormalizedFallback_CombinedCaseAccentWhitespaceMatches(t *testing.T) {
|
||||||
|
invalid := testUserPrefix + "8 Rue de Verdun Nantes"
|
||||||
|
correct := testUserPrefix + "8 Rue de Verdun, 44000 Nantes"
|
||||||
|
addCorrectionForFallback(t, invalid, correct)
|
||||||
|
|
||||||
|
cmd := &models.Command{DeliveryAddress: testUserPrefix + "8 RUE de verdun nantes "}
|
||||||
|
err := testDB.CheckAddress(cmd)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("attendu une erreur signalant la correction (casse + espaces combinés)")
|
||||||
|
}
|
||||||
|
if cmd.DeliveryAddress != correct {
|
||||||
|
t.Errorf("adresse corrigée: got=%q want=%q", cmd.DeliveryAddress, correct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Le fallback compare une égalité normalisée stricte, pas une similarité
|
||||||
|
// floue : une adresse réellement différente (même partiellement proche) ne
|
||||||
|
// doit jamais être substituée par erreur.
|
||||||
|
func TestCheckAddress_NormalizedFallback_DoesNotMatchDifferentAddress(t *testing.T) {
|
||||||
|
invalid := testUserPrefix + "12 Rue Crebillon Nantes"
|
||||||
|
correct := testUserPrefix + "12 Rue Crébillon, 44000 Nantes"
|
||||||
|
addCorrectionForFallback(t, invalid, correct)
|
||||||
|
|
||||||
|
cmd := &models.Command{DeliveryAddress: testUserPrefix + "14 Rue Crebillon Nantes"}
|
||||||
|
original := cmd.DeliveryAddress
|
||||||
|
if err := testDB.CheckAddress(cmd); err != nil {
|
||||||
|
t.Fatalf("une adresse différente ne doit pas déclencher de correction: %v", err)
|
||||||
|
}
|
||||||
|
if cmd.DeliveryAddress != original {
|
||||||
|
t.Errorf("adresse ne doit pas être modifiée: got=%q want=%q", cmd.DeliveryAddress, original)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avec plusieurs corrections enregistrées, le fallback doit retrouver la
|
||||||
|
// bonne entrée (pas la première venue) même via une variante normalisée.
|
||||||
|
func TestCheckAddress_NormalizedFallback_FindsRightEntryAmongMultiple(t *testing.T) {
|
||||||
|
invalidA := testUserPrefix + "1 Rue A Nantes"
|
||||||
|
correctA := testUserPrefix + "1 Rue A, 44000 Nantes"
|
||||||
|
invalidB := testUserPrefix + "2 Rue B Nantes"
|
||||||
|
correctB := testUserPrefix + "2 Rue B, 44000 Nantes"
|
||||||
|
addCorrectionForFallback(t, invalidA, correctA)
|
||||||
|
addCorrectionForFallback(t, invalidB, correctB)
|
||||||
|
|
||||||
|
cmd := &models.Command{DeliveryAddress: testUserPrefix + "2 RUE b nantes"}
|
||||||
|
if err := testDB.CheckAddress(cmd); err == nil {
|
||||||
|
t.Fatal("attendu une erreur signalant la correction B")
|
||||||
|
}
|
||||||
|
if cmd.DeliveryAddress != correctB {
|
||||||
|
t.Errorf("adresse corrigée: got=%q want=%q (ne doit pas confondre avec A)", cmd.DeliveryAddress, correctB)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAddAddress_ThenAllAddressIncludesIt(t *testing.T) {
|
func TestAddAddress_ThenAllAddressIncludesIt(t *testing.T) {
|
||||||
invalid := testUserPrefix + "adresse invalide test"
|
invalid := testUserPrefix + "adresse invalide test"
|
||||||
correct := testUserPrefix + "adresse correcte test"
|
correct := testUserPrefix + "adresse correcte test"
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gestion/utils"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// utils.NormalizeAddress supprime les accents et normalise les espaces, mais
|
||||||
|
// ne touche PAS à la casse — les appelants qui veulent une comparaison
|
||||||
|
// insensible à la casse doivent combiner avec strings.EqualFold ou
|
||||||
|
// strings.ToLower (voir services/adresses_correction.go et db/db_address.go).
|
||||||
|
// Ce fichier fixe ce contrat par des tests, pour éviter qu'un futur appelant
|
||||||
|
// suppose à tort que la casse est déjà gérée.
|
||||||
|
|
||||||
|
func TestNormalizeAddress_RemovesAccents(t *testing.T) {
|
||||||
|
got := utils.NormalizeAddress("12 Rue Crébillon, Nantés")
|
||||||
|
want := "12 Rue Crebillon, Nantes"
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("got=%q want=%q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNormalizeAddress_CollapsesMultipleAndTrailingSpaces(t *testing.T) {
|
||||||
|
got := utils.NormalizeAddress(" 12 Rue de la Paix ")
|
||||||
|
want := "12 Rue de la Paix"
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("got=%q want=%q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNormalizeAddress_DoesNotChangeCase(t *testing.T) {
|
||||||
|
// Contrat volontaire : NormalizeAddress n'abaisse pas la casse. Un
|
||||||
|
// appelant qui veut une comparaison insensible à la casse doit le faire
|
||||||
|
// explicitement (strings.EqualFold côté appelant).
|
||||||
|
got := utils.NormalizeAddress("Rue De La Paix")
|
||||||
|
if got == strings.ToLower(got) {
|
||||||
|
t.Fatalf("ce test suppose une entrée avec des majuscules significatives, corrige le cas de test")
|
||||||
|
}
|
||||||
|
if got != "Rue De La Paix" {
|
||||||
|
t.Errorf("NormalizeAddress ne doit pas modifier la casse: got=%q", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNormalizeAddress_EmptyStringReturnsEmpty(t *testing.T) {
|
||||||
|
if got := utils.NormalizeAddress(""); got != "" {
|
||||||
|
t.Errorf("got=%q want=%q", got, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNormalizeAddress_CombinedAccentsAndSpaces(t *testing.T) {
|
||||||
|
got := utils.NormalizeAddress(" 20 Boulevard Général de Gaulle, Nantés ")
|
||||||
|
want := "20 Boulevard General de Gaulle, Nantes"
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("got=%q want=%q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user