From 1edfd3243c8bc69ad3ff296d24e6a9441160811b Mon Sep 17 00:00:00 2001
From: philippe tcheriatinsky <philippe.tcherniatinsky@inrae.fr>
Date: Mon, 24 Feb 2025 14:01:42 +0100
Subject: [PATCH 1/6] Correction #13
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Ajout d'un vérificateur et envoie d'une error
---
 .../configuration/ConfigurationException.java |  2 +-
 .../configuration/builder/DataBuilder.java    | 63 ++++++++++++++++---
 .../oresing/rest/TestReferencesErrors.java    | 23 ++++---
 3 files changed, 70 insertions(+), 18 deletions(-)

diff --git a/src/main/java/fr/inra/oresing/domain/exceptions/configuration/ConfigurationException.java b/src/main/java/fr/inra/oresing/domain/exceptions/configuration/ConfigurationException.java
index a664cab..9ffbd3a 100644
--- a/src/main/java/fr/inra/oresing/domain/exceptions/configuration/ConfigurationException.java
+++ b/src/main/java/fr/inra/oresing/domain/exceptions/configuration/ConfigurationException.java
@@ -227,7 +227,7 @@ public enum ConfigurationException {
     INVALID_CONFIGURATION_FILE,
     ADDING_AUTHORIZATION_SCOPE_ATTRIBUTES_ERROR,
     REMOVING_AUTHORIZATION_SCOPE_ATTRIBUTES_ERROR,
-
+    MISSING_COMPONENT_FOR_DISPLAY_PATTERN,
     /*
     jackson parse exeption
      */
diff --git a/src/main/java/fr/inra/oresing/rest/model/configuration/builder/DataBuilder.java b/src/main/java/fr/inra/oresing/rest/model/configuration/builder/DataBuilder.java
index 0bf0cbf..11d1a87 100644
--- a/src/main/java/fr/inra/oresing/rest/model/configuration/builder/DataBuilder.java
+++ b/src/main/java/fr/inra/oresing/rest/model/configuration/builder/DataBuilder.java
@@ -11,10 +11,14 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.MapUtils;
 
 import java.util.*;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 public record DataBuilder(RootBuilder rootBuilder) {
 
+    public static final Pattern DISPLAY_MATCHING_GROUP = Pattern.compile("\\{([^}]+)\\}");
+
     Parsing<StandardDataDescription> build(final String path, final String dataKey, final JsonNode jsonNode, I18n i18n) {
         final Set<Tag> tags = buildAndTestDomainTags(path, jsonNode);
 
@@ -71,8 +75,8 @@ public record DataBuilder(RootBuilder rootBuilder) {
         final List<String> listComponentKeys = rootBuilder.getListComponentKeys(dataKey);
 
         final Map<String, Map> localizationDisplay = rootBuilder.getMapper().convertValue(
-                jsonNode.findPath(ConfigurationSchemaNode.OA_I_18_N_DISPLAY_PATTERN)
-                        .findPath(ConfigurationSchemaNode.OA_PATTERN), Map.class);
+                jsonNode.findPath(ConfigurationSchemaNode.OA_I_18_N_DISPLAY_PATTERN), Map.class);
+        testLocalizationDisplay(localizationDisplay, listComponentKeys, path);
         try {
             i18n = i18n.add(
                     NodeSchemaValidator.joinI18nPath(
@@ -103,9 +107,9 @@ public record DataBuilder(RootBuilder rootBuilder) {
                         entry -> entry.getValue().importHeader()
                 )).entrySet().stream()
                 .filter(entry -> entry.getValue().size() > 1)
-                .filter(entry->!(entry.getValue().stream().allMatch(value-> (value.getValue() instanceof PatternComponentQualifiers) || (value.getValue() instanceof PatternComponentAdjacents))))
+                .filter(entry -> !(entry.getValue().stream().allMatch(value -> (value.getValue() instanceof PatternComponentQualifiers) || (value.getValue() instanceof PatternComponentAdjacents))))
                 .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
-        if (MapUtils.isNotEmpty(duplicatedImportHeader)){
+        if (MapUtils.isNotEmpty(duplicatedImportHeader)) {
             duplicatedImportHeader.forEach((key, value) -> rootBuilder.buildError(ConfigurationException.DUPLICATED_COMPONENT_HEADER,
                     Map.of(
                             "data", dataKey,
@@ -124,10 +128,10 @@ public record DataBuilder(RootBuilder rootBuilder) {
         Map<CheckerDescription.CheckerDescriptionType, List<String>> componentValidationsByType = getComponentValidationsByType(validations);
         HashMap<String, ComponentDescription> localComponentDescription = new HashMap<>(componentDescriptions);
         final Parsing<Submission> submissionParsing = rootBuilder.getSubmissionBuilder().buildSubmission(i18n, dataKey, jsonNode, localComponentDescription);
-        if(
+        if (
                 tags.stream().noneMatch(Tag.DataTag.class::isInstance) &&
                 Optional.of(submissionParsing).map(Parsing::result).map(Submission::strategy).filter(SubmissionType.OA_VERSIONING::equals).isPresent()
-                ){
+        ) {
             rootBuilder.buildError(ConfigurationException.UNEXPECTED_SUBMISSION,
                     Map.of()
                     , path);
@@ -167,6 +171,51 @@ public record DataBuilder(RootBuilder rootBuilder) {
                 ));
     }
 
+    private boolean testLocalizationDisplay(Map<String, Map> localizationDisplay, List<String> listComponentKeys, String path) {
+        if (MapUtils.isEmpty(localizationDisplay)) {
+            return true;
+        }
+        for (String group : List.of(ConfigurationSchemaNode.OA_TITLE, ConfigurationSchemaNode.OA_DESCRIPTION)) {
+            if (localizationDisplay.containsKey(group)) {
+                for (Object language : localizationDisplay.get(group).keySet()) {
+                    boolean test = testLocalizationDisplay(
+                            localizationDisplay.get(group).get(language).toString(),
+                            listComponentKeys,
+                            path,
+                            group,
+                            language.toString());
+                    if (!test) {
+                        return test;
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    private boolean testLocalizationDisplay(String matchingGroup, List<String> listComponentKeys, String path, String group, String language) {
+        Pattern pattern = DISPLAY_MATCHING_GROUP;
+        List<String> list = pattern.matcher(matchingGroup)
+                .results()
+                .map(m -> m.group(1))
+                .filter(Predicate.not(listComponentKeys::contains))
+                .toList();
+        list.stream().forEach(
+                badGroup -> rootBuilder.buildError(ConfigurationException.MISSING_COMPONENT_FOR_DISPLAY_PATTERN,
+                        Map.of(
+                                "badGroup", badGroup,
+                                "expectedComponent", listComponentKeys
+                        ),
+                        NodeSchemaValidator.joinPath(
+                                path,
+                                group,
+                                language
+                        )
+                )
+        );
+        return list.isEmpty();
+    }
+
     private Map<CheckerDescription.CheckerDescriptionType, List<String>> getComponentValidationsByType(ImmutableMap<String, ValidationDescription> validations) {
         Map<CheckerDescription.CheckerDescriptionType, List<String>> componentValidationByType = new HashMap<>();
         for (ValidationDescription validation : validations.values()) {
@@ -185,7 +234,7 @@ public record DataBuilder(RootBuilder rootBuilder) {
 
 
     private Set<Tag> buildAndTestDomainTags(final String path, final JsonNode jsonNode) {
-        if(jsonNode.get(ConfigurationSchemaNode.OA_TAGS)==null){
+        if (jsonNode.get(ConfigurationSchemaNode.OA_TAGS) == null) {
             return Collections.emptySet();
         }
         final Set<String> domainTagNames = rootBuilder.getDomainTags().stream()
diff --git a/src/test/java/fr/inra/oresing/rest/TestReferencesErrors.java b/src/test/java/fr/inra/oresing/rest/TestReferencesErrors.java
index 31cb2f2..e0e4de3 100644
--- a/src/test/java/fr/inra/oresing/rest/TestReferencesErrors.java
+++ b/src/test/java/fr/inra/oresing/rest/TestReferencesErrors.java
@@ -60,6 +60,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 public class TestReferencesErrors {
 
     public static final Map<String, String> responses = new HashMap<>();
+    public static final String LOGIN = "poussinreferenceserrors";
+    public static final String PASSWORD = "xxxxxxxx";
+    public static final String EMAIL = "poussinreferenceserrors@inrae.fr";
     @Autowired
     private ObjectMapper objectMapper;
     @Autowired
@@ -86,13 +89,13 @@ public class TestReferencesErrors {
 
     @BeforeEach
     public void createUser() throws Exception {
-        CreateUserResult authUser = authenticationService.createUser("poussin", "xxxxxxxx", "poussin@inrae.fr");
+        CreateUserResult authUser = authenticationService.createUser(LOGIN, PASSWORD, EMAIL);
         final UUID userId = authUser.userId();
         setToActive(userId);
-        final CreateUserResult lambdaUser = authenticationService.createUser("lambda", "xxxxxxxx", "lamnda@inrae.fr");
+        final CreateUserResult lambdaUser = authenticationService.createUser("lambda", PASSWORD, "lamnda@inrae.fr");
         authCookie = mockMvc.perform(post("/api/v1/login")
-                        .param("login", "poussin")
-                        .param("password", "xxxxxxxx"))
+                        .param("login", LOGIN)
+                        .param("password", PASSWORD))
                 .andReturn().getResponse().getCookie(AuthHelper.JWT_COOKIE_NAME);
         addRoleAdmin(authUser);
     }
@@ -140,13 +143,13 @@ public class TestReferencesErrors {
         try (final InputStream in = Objects.requireNonNull(resource).openStream()) {
             final MockMultipartFile configuration = new MockMultipartFile("file", "recursivity.yaml", "text/plain", in);
             //définition de l'application
-            CreateUserResult recursivityUser = authenticationService.createUser("recursivity", "xxxxxxxx", "recursivity@inrae.fr");
+            CreateUserResult recursivityUser = authenticationService.createUser("recursivity", PASSWORD, "recursivity@inrae.fr");
             setToActive(recursivityUser.userId());
             final UUID recursivityUserId = recursivityUser.userId();
             addUserRightCreateApplication(recursivityUserId, "recursivite");
             recursivityCookie = mockMvc.perform(post("/api/v1/login")
                             .param("login", "recursivity")
-                            .param("password", "xxxxxxxx"))
+                            .param("password", PASSWORD))
                     .andReturn().getResponse().getCookie(AuthHelper.JWT_COOKIE_NAME);
             final String id = fixtures.getIdFromApplicationResult(fixtures.loadApplication(configuration, recursivityCookie, "recursivite", ""));
             final String response = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/applications/recursivite")
@@ -267,13 +270,13 @@ public class TestReferencesErrors {
         final Cookie repeatedColumnCookie;
         try (final InputStream in = Objects.requireNonNull(resource).openStream()) {
             final MockMultipartFile configuration = new MockMultipartFile("file", "repeatedcolumns.yaml", "text/plain", in);
-            CreateUserResult recursivityUser = authenticationService.createUser("repeatedcolumns", "xxxxxxxx", "repeatedcolumns@inrae.fr");
+            CreateUserResult recursivityUser = authenticationService.createUser("repeatedcolumns", PASSWORD, "repeatedcolumns@inrae.fr");
             setToActive(recursivityUser.userId());
             final UUID recursivityUserId = recursivityUser.userId();
             addUserRightCreateApplication(recursivityUserId, "repeatedcolumns");
             repeatedColumnCookie = mockMvc.perform(post("/api/v1/login")
                             .param("login", "repeatedcolumns")
-                            .param("password", "xxxxxxxx"))
+                            .param("password", PASSWORD))
                     .andReturn().getResponse().getCookie(AuthHelper.JWT_COOKIE_NAME);
             final String id = fixtures.getIdFromApplicationResult(fixtures.loadApplication(configuration, repeatedColumnCookie, "repeatedcolumns", ""));
 
@@ -344,13 +347,13 @@ public class TestReferencesErrors {
         final Cookie repeatedColumnsCookie;
         try (final InputStream in = Objects.requireNonNull(resource).openStream()) {
             final MockMultipartFile configuration = new MockMultipartFile("file", "repeatedcolumns.yaml", "text/plain", in);
-            CreateUserResult recursivityUser = authenticationService.createUser("repeatedcolumns", "xxxxxxxx", "repeatedcolumns@inrae.fr");
+            CreateUserResult recursivityUser = authenticationService.createUser("repeatedcolumns", PASSWORD, "repeatedcolumns@inrae.fr");
             setToActive(recursivityUser.userId());
             final UUID recursivityUserId = recursivityUser.userId();
             addUserRightCreateApplication(recursivityUserId, "repeatedcolumns");
             repeatedColumnsCookie = mockMvc.perform(post("/api/v1/login")
                             .param("login", "repeatedcolumns")
-                            .param("password", "xxxxxxxx"))
+                            .param("password", PASSWORD))
                     .andReturn().getResponse().getCookie(AuthHelper.JWT_COOKIE_NAME);
             final String id = fixtures.getIdFromApplicationResult(fixtures.loadApplication(configuration, repeatedColumnsCookie, "repeatedcolumns", ""));
             final String response = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/applications/repeatedcolumns")
-- 
GitLab


From 89a8ddc64cd90b9a901c481ee0db487b2046e99c Mon Sep 17 00:00:00 2001
From: philippe tcheriatinsky <philippe.tcherniatinsky@inrae.fr>
Date: Mon, 24 Feb 2025 14:05:42 +0100
Subject: [PATCH 2/6] Renvoie de outes les erreurs

---
 .../rest/model/configuration/builder/DataBuilder.java     | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/main/java/fr/inra/oresing/rest/model/configuration/builder/DataBuilder.java b/src/main/java/fr/inra/oresing/rest/model/configuration/builder/DataBuilder.java
index 11d1a87..3c54eb0 100644
--- a/src/main/java/fr/inra/oresing/rest/model/configuration/builder/DataBuilder.java
+++ b/src/main/java/fr/inra/oresing/rest/model/configuration/builder/DataBuilder.java
@@ -175,22 +175,20 @@ public record DataBuilder(RootBuilder rootBuilder) {
         if (MapUtils.isEmpty(localizationDisplay)) {
             return true;
         }
+        boolean isValid = true;
         for (String group : List.of(ConfigurationSchemaNode.OA_TITLE, ConfigurationSchemaNode.OA_DESCRIPTION)) {
             if (localizationDisplay.containsKey(group)) {
                 for (Object language : localizationDisplay.get(group).keySet()) {
-                    boolean test = testLocalizationDisplay(
+                    isValid = isValid && testLocalizationDisplay(
                             localizationDisplay.get(group).get(language).toString(),
                             listComponentKeys,
                             path,
                             group,
                             language.toString());
-                    if (!test) {
-                        return test;
-                    }
                 }
             }
         }
-        return true;
+        return isValid;
     }
 
     private boolean testLocalizationDisplay(String matchingGroup, List<String> listComponentKeys, String path, String group, String language) {
-- 
GitLab


From f4826fe333467bcd2d8c92a7a4f653b138f5b748 Mon Sep 17 00:00:00 2001
From: philippe tcheriatinsky <philippe.tcherniatinsky@inrae.fr>
Date: Mon, 24 Feb 2025 14:52:19 +0100
Subject: [PATCH 3/6] L'erreur met en exergue un test avec une fichier de
 configuration invalide

---
 .../rest/model/configuration/builder/DataBuilder.java  |  3 ++-
 .../resources/data/configuration/configuration.yaml    | 10 +++++-----
 .../data/configuration/localization.result.json        | 10 +++++-----
 3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/src/main/java/fr/inra/oresing/rest/model/configuration/builder/DataBuilder.java b/src/main/java/fr/inra/oresing/rest/model/configuration/builder/DataBuilder.java
index 3c54eb0..d6ccec3 100644
--- a/src/main/java/fr/inra/oresing/rest/model/configuration/builder/DataBuilder.java
+++ b/src/main/java/fr/inra/oresing/rest/model/configuration/builder/DataBuilder.java
@@ -198,7 +198,8 @@ public record DataBuilder(RootBuilder rootBuilder) {
                 .map(m -> m.group(1))
                 .filter(Predicate.not(listComponentKeys::contains))
                 .toList();
-        list.stream().forEach(
+        list.stream()
+                .forEach(
                 badGroup -> rootBuilder.buildError(ConfigurationException.MISSING_COMPONENT_FOR_DISPLAY_PATTERN,
                         Map.of(
                                 "badGroup", badGroup,
diff --git a/src/test/resources/data/configuration/configuration.yaml b/src/test/resources/data/configuration/configuration.yaml
index 06c4e7a..a8a1481 100644
--- a/src/test/resources/data/configuration/configuration.yaml
+++ b/src/test/resources/data/configuration/configuration.yaml
@@ -97,7 +97,7 @@ OA_data:
         en: Sites list
     OA_i18nDisplayPattern:
       OA_title:
-        fr: '{zet_nom_fry}'
+        fr: '{zet_nom_fr}'
         en: '{zet_nom_en}'
       OA_description:
         fr: '{zet_description_fr}'
@@ -820,11 +820,11 @@ OA_data:
         en: remote sensing data plot
     OA_i18nDisplayPattern: # attention : avec un S ici car peut concerner plusieurs referentiels
       OA_title:
-          fr: "<em>[data display]</em>: {sit_code} ({sit_label_fr})"
-          en: "<em>[data display]</em>: {sit_code} ({sit_label_en})"
+          fr: "<em>[data display]</em>: {tel_experimental_site} ({tel_experimental_plot})"
+          en: "<em>[data display]</em>: {tel_experimental_site} ({tel_experimental_plot})"
       OA_description:
-          fr: "<em>[data display]</em>: {sit_code} ({sit_label_fr})"
-          en: "<em>[data display]</em>: {sit_code} ({sit_label_en})"
+          fr: "<em>[data display]</em>: {tel_experimental_site} ({tel_experimental_plot})"
+          en: "<em>[data display]</em>: {tel_experimental_site} ({tel_experimental_plot})"
     OA_naturalKey: # clé d'unicité pour chaque ligne de données
       - tel_experimental_plot
       - tel_experimental_site
diff --git a/src/test/resources/data/configuration/localization.result.json b/src/test/resources/data/configuration/localization.result.json
index eb9cabf..05c0d0e 100644
--- a/src/test/resources/data/configuration/localization.result.json
+++ b/src/test/resources/data/configuration/localization.result.json
@@ -218,7 +218,7 @@
       "i18nDisplayPattern" : {
         "title" : {
           "en" : "{zet_nom_en}",
-          "fr" : "{zet_nom_fry}"
+          "fr" : "{zet_nom_fr}"
         },
         "description" : {
           "en" : "{zet_description_en}",
@@ -379,12 +379,12 @@
       },
       "i18nDisplayPattern" : {
         "title" : {
-          "en" : "<em>[data display]</em>: {sit_code} ({sit_label_en})",
-          "fr" : "<em>[data display]</em>: {sit_code} ({sit_label_fr})"
+          "en" : "<em>[data display]</em>: {tel_experimental_site} ({tel_experimental_plot})",
+          "fr" : "<em>[data display]</em>: {tel_experimental_site} ({tel_experimental_plot})"
         },
         "description" : {
-          "en" : "<em>[data display]</em>: {sit_code} ({sit_label_en})",
-          "fr" : "<em>[data display]</em>: {sit_code} ({sit_label_fr})"
+          "en" : "<em>[data display]</em>: {tel_experimental_site} ({tel_experimental_plot})",
+          "fr" : "<em>[data display]</em>: {tel_experimental_site} ({tel_experimental_plot})"
         }
       },
       "i18n" : {
-- 
GitLab


From 983e6d5e3ba9f02b7527297bc3e76eafd2f3c3f6 Mon Sep 17 00:00:00 2001
From: lucile varloteaux <lucile.varloteaux@inrae.fr>
Date: Wed, 26 Feb 2025 10:02:49 +0100
Subject: [PATCH 4/6] test backend fait pour
 MISSING_COMPONENT_FOR_DISPLAY_PATTERN

---
 .../ApplicationConfigurationServiceTest.java  | 33 ++++++++++++++++---
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/src/test/java/fr/inra/oresing/rest/ApplicationConfigurationServiceTest.java b/src/test/java/fr/inra/oresing/rest/ApplicationConfigurationServiceTest.java
index 30b034e..b3915ab 100644
--- a/src/test/java/fr/inra/oresing/rest/ApplicationConfigurationServiceTest.java
+++ b/src/test/java/fr/inra/oresing/rest/ApplicationConfigurationServiceTest.java
@@ -1357,8 +1357,8 @@ public class ApplicationConfigurationServiceTest {
     }
 
     @Test
-    public void testduplicatedHeader() {
-        CONFIGURATION_INSTANCE.builder("testUnsuportedI18nKeyLanguageInValidation")
+    public void testDuplicatedHeader() {
+        CONFIGURATION_INSTANCE.builder("testDuplicatedHeader")
                 .withReplace("OA_headerName: \"Nom de la clé du site\"",
                         "OA_headerName: \"zet_chemin_parent\"")
                 .test(errors -> {
@@ -1376,8 +1376,8 @@ public class ApplicationConfigurationServiceTest {
     }
 
     @Test
-    public void testduplicatedComponent() {
-        CONFIGURATION_INSTANCE.builder("testUnsuportedI18nKeyLanguageInValidation")
+    public void testDuplicatedComponent() {
+        CONFIGURATION_INSTANCE.builder("testDuplicatedComponent")
                 .withReplace("tel_value",
                         "tel_experimental_site")
                 .test(errors -> {
@@ -1392,6 +1392,31 @@ public class ApplicationConfigurationServiceTest {
                 });
     }
 
+    @Test
+    public void testMissingComponentForDisplayPattern() {
+        CONFIGURATION_INSTANCE.builder("testMissingComponentForDisplayPattern")
+                .withReplace("    OA_i18nDisplayPattern:\n" +
+                             "      OA_title:\n" +
+                             "        fr: \"{esp_nom}\"\n" +
+                             "        en: \"{esp_nom}\"",
+                        "    OA_i18nDisplayPattern:\n" +
+                        "      OA_title:\n" +
+                        "        fr: \"{esp_invalid_nom}\"\n" +
+                        "        en: \"{esp_nom}\"")
+                .test(errors -> {
+                    assertEquals(1, errors.size());
+                    final ValidationError validationError = errors.getFirst();
+                    assertEquals(ConfigurationException.MISSING_COMPONENT_FOR_DISPLAY_PATTERN.getMessage(), validationError.getMessage());
+
+                    final Set<String> expected = Arrays.stream(new String[]{"colonne_homonyme_entre_referentiels", "my_computed_column", "esp_definition_en", "esp_definition_fr", "esp_nom"})
+                            .collect(Collectors.toCollection(TreeSet::new));
+                    final Set<String> given = new TreeSet<>((Collection<? extends String>) validationError.getParam("expectedComponent"));
+                    assertEquals(expected, given);
+                    assertEquals("esp_invalid_nom", validationError.getParam("badGroup"));
+                    assertEquals("OA_data > especes > OA_title > fr", validationError.getParam("path"));
+                });
+    }
+
     @Test
     public void testduplicatedComponentInPatternComponent() {
         CONFIGURATION_INSTANCE.builder("testduplicatedComponentInPatternComponent")
-- 
GitLab


From f2479f48bbaf5d4e6e52dacde89f2175216f35b1 Mon Sep 17 00:00:00 2001
From: philippe tcheriatinsky <philippe.tcherniatinsky@inrae.fr>
Date: Fri, 28 Feb 2025 11:14:13 +0100
Subject: [PATCH 5/6] Jout d'un test sur les Handlers

---
 .../InvalidDatasetContentException.java       |   2 +-
 .../BadApplicationConfigurationException.java |   2 +-
 .../configuration/ConfigurationException.java |   1 +
 .../ApplicationConfigurationServiceTest.java  |   5 +-
 .../exceptions/OreExceptionHandlerTest.java   | 217 ++++++++++++++++++
 5 files changed, 221 insertions(+), 6 deletions(-)
 create mode 100644 src/test/java/fr/inra/oresing/rest/exceptions/OreExceptionHandlerTest.java

diff --git a/src/main/java/fr/inra/oresing/domain/checker/InvalidDatasetContentException.java b/src/main/java/fr/inra/oresing/domain/checker/InvalidDatasetContentException.java
index 8e1faec..7991c62 100644
--- a/src/main/java/fr/inra/oresing/domain/checker/InvalidDatasetContentException.java
+++ b/src/main/java/fr/inra/oresing/domain/checker/InvalidDatasetContentException.java
@@ -27,7 +27,7 @@ public class InvalidDatasetContentException extends OreSiTechnicalException {
 
     private final List<CsvRowValidationCheckResult> errors;
 
-    private InvalidDatasetContentException(final List<CsvRowValidationCheckResult> errors) {
+    public InvalidDatasetContentException(final List<CsvRowValidationCheckResult> errors) {
         super("Erreurs rencontrées à l'import du fichier");
         this.errors = errors;
     }
diff --git a/src/main/java/fr/inra/oresing/domain/exceptions/configuration/BadApplicationConfigurationException.java b/src/main/java/fr/inra/oresing/domain/exceptions/configuration/BadApplicationConfigurationException.java
index 4279f32..4959a36 100644
--- a/src/main/java/fr/inra/oresing/domain/exceptions/configuration/BadApplicationConfigurationException.java
+++ b/src/main/java/fr/inra/oresing/domain/exceptions/configuration/BadApplicationConfigurationException.java
@@ -8,7 +8,7 @@ public class BadApplicationConfigurationException extends OreSiTechnicalExceptio
 
     private final ConfigurationException configurationException;
 
-    private BadApplicationConfigurationException(final String message, final ConfigurationException configurationException) {
+    public BadApplicationConfigurationException(final String message, final ConfigurationException configurationException) {
         super(message);
         this.configurationException = configurationException;
     }
diff --git a/src/main/java/fr/inra/oresing/domain/exceptions/configuration/ConfigurationException.java b/src/main/java/fr/inra/oresing/domain/exceptions/configuration/ConfigurationException.java
index 9ffbd3a..17cac12 100644
--- a/src/main/java/fr/inra/oresing/domain/exceptions/configuration/ConfigurationException.java
+++ b/src/main/java/fr/inra/oresing/domain/exceptions/configuration/ConfigurationException.java
@@ -225,6 +225,7 @@ public enum ConfigurationException {
     DUPLICATED_COMPONENT_HEADER,
     DUPLICATED_COMPONENT_HEADER_IN_PATTERN_COMPONENT,
     INVALID_CONFIGURATION_FILE,
+    IO_EXCEPTION,
     ADDING_AUTHORIZATION_SCOPE_ATTRIBUTES_ERROR,
     REMOVING_AUTHORIZATION_SCOPE_ATTRIBUTES_ERROR,
     MISSING_COMPONENT_FOR_DISPLAY_PATTERN,
diff --git a/src/test/java/fr/inra/oresing/rest/ApplicationConfigurationServiceTest.java b/src/test/java/fr/inra/oresing/rest/ApplicationConfigurationServiceTest.java
index b3915ab..d0ca91f 100644
--- a/src/test/java/fr/inra/oresing/rest/ApplicationConfigurationServiceTest.java
+++ b/src/test/java/fr/inra/oresing/rest/ApplicationConfigurationServiceTest.java
@@ -16,7 +16,6 @@ import fr.inra.oresing.rest.services.ApplicationConfigurationService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.IOUtils;
 import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -1529,9 +1528,7 @@ public class ApplicationConfigurationServiceTest {
                     default -> log.info("test terminé");
                 }
             } catch (final IOException e) {
-                throw new OreSiTechnicalException("impossible de lire le fichier de test", e);
-            } catch (final BadApplicationConfigurationException e) {
-                //errors.put(methodName, e);
+                throw new BadApplicationConfigurationException("impossible de lire le fichier de test", ConfigurationException.IO_EXCEPTION);
             }
         }
 
diff --git a/src/test/java/fr/inra/oresing/rest/exceptions/OreExceptionHandlerTest.java b/src/test/java/fr/inra/oresing/rest/exceptions/OreExceptionHandlerTest.java
new file mode 100644
index 0000000..dce92a3
--- /dev/null
+++ b/src/test/java/fr/inra/oresing/rest/exceptions/OreExceptionHandlerTest.java
@@ -0,0 +1,217 @@
+package fr.inra.oresing.rest.exceptions;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableMap;
+import fr.inra.oresing.ValidationLevel;
+import fr.inra.oresing.domain.OreSiUser;
+import fr.inra.oresing.domain.authorization.privilegeassessor.exception.DisconnectedException;
+import fr.inra.oresing.domain.checker.InvalidDatasetContentException;
+import fr.inra.oresing.domain.checker.type.BooleanType;
+import fr.inra.oresing.domain.data.deposit.validation.CsvRowValidationCheckResult;
+import fr.inra.oresing.domain.data.deposit.validation.validationcheckresults.BooleanValidationCheckResult;
+import fr.inra.oresing.domain.exceptions.OreSiTechnicalException;
+import fr.inra.oresing.domain.exceptions.SiOreIllegalArgumentException;
+import fr.inra.oresing.domain.exceptions.application.NoSuchApplicationException;
+import fr.inra.oresing.domain.exceptions.binaryfile.binaryfile.BadFileOrUUIDQuery;
+import fr.inra.oresing.domain.exceptions.configuration.BadApplicationConfigurationException;
+import fr.inra.oresing.domain.exceptions.configuration.ConfigurationException;
+import fr.inra.oresing.domain.exceptions.data.data.BadBinaryFileDatasetQuery;
+import fr.inra.oresing.domain.exceptions.data.data.BadDownloadDatasetQuery;
+import fr.inra.oresing.persistence.AuthenticationFailure;
+import fr.inra.oresing.rest.model.configuration.ValidationError;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.postgresql.util.PSQLException;
+import org.springframework.http.ResponseEntity;
+import org.springframework.jdbc.BadSqlGrammarException;
+import org.springframework.validation.ObjectError;
+import org.springframework.web.bind.support.WebExchangeBindException;
+
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.when;
+
+class OreExceptionHandlerTest {
+    private OreExceptionHandler exceptionHandler;
+    private ObjectMapper objectMapper;
+
+    @Mock
+    private WebExchangeBindException webExchangeBindException;
+
+    @Mock
+    private BadSqlGrammarException badSqlGrammarException;
+
+    @Mock
+    private PSQLException psqlException;
+
+    @BeforeEach
+    public void setUp() {
+        MockitoAnnotations.openMocks(this);
+        exceptionHandler = new OreExceptionHandler();
+        objectMapper = new ObjectMapper();
+
+        // Configuration des mocks
+        when(webExchangeBindException.getAllErrors()).thenReturn(List.of(new ObjectError("test", "message")));
+        when(badSqlGrammarException.getMessage()).thenReturn("SQL error");
+    }
+
+    @Test
+    public void testValidationErrorSerializability() {
+        ValidationError error = new ValidationError("Test error");
+        ResponseEntity<ValidationError> response = exceptionHandler.handle(error);
+
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(response.getBody()));
+    }
+
+    @Test
+    public void testDisconnectedExceptionSerializability() {
+        DisconnectedException exception = new DisconnectedException("User disconnected");
+        ResponseEntity<DisconnectedException> response = exceptionHandler.handle(exception);
+
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(response.getBody()));
+    }
+
+    @Test
+    public void testSiOreIllegalArgumentExceptionSerializability() {
+        SiOreIllegalArgumentException exception = new SiOreIllegalArgumentException("Illegal argument", Map.of("param", "param"));
+        ResponseEntity<SiOreIllegalArgumentException> response = exceptionHandler.handle(exception);
+
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(response.getBody()));
+    }
+
+    @Test
+    public void testAuthenticationFailureSerializability() {
+        // Tester différents cas de AuthenticationFailure
+        testAuthFailureCase("INACTIVE_ACCOUNT");
+        testAuthFailureCase("EXISTING_LOGIN");
+        testAuthFailureCase("BAD_LOGIN_PASSWORD");
+        testAuthFailureCase("BAD_PASSWORDS");
+        testAuthFailureCase("BAD_VALIDATION_KEY");
+        testAuthFailureCase("DEFAULT_CASE");
+    }
+
+    private void testAuthFailureCase(String message) {
+        OreSiUser oreSiUser = new OreSiUser();
+        oreSiUser.setId( UUID.randomUUID());
+        oreSiUser.setLogin("testuser");
+        oreSiUser.setEmail("test@example.com");
+        oreSiUser.setAccountstate(OreSiUser.OreSiUserStates.active);
+
+        AuthenticationFailure failure = new AuthenticationFailure(message,
+                oreSiUser
+        );
+        ResponseEntity<AuthenticationFailure> response = exceptionHandler.handle(failure);
+
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(response.getBody()));
+    }
+
+    @Test
+    public void testWebExchangeBindExceptionSerializability() {
+        List<ObjectError> errors = exceptionHandler.exception(webExchangeBindException);
+
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(errors));
+    }
+
+    @Test
+    public void testBadSqlGrammarExceptionSerializability() {
+        when(badSqlGrammarException.getCause()).thenReturn(psqlException);
+        when(psqlException.getMessage()).thenReturn("permission denied");
+
+        ResponseEntity<String> response = exceptionHandler.handle(badSqlGrammarException);
+
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(response.getBody()));
+    }
+
+    @Test
+    public void testNoSuchApplicationExceptionSerializability() {
+        NoSuchApplicationException exception = new NoSuchApplicationException("Application not found");
+        ResponseEntity<String> response = exceptionHandler.handle(exception);
+
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(response.getBody()));
+    }
+
+    @Test
+    public void testBadApplicationConfigurationExceptionSerializability() {
+        ConfigurationException configException = ConfigurationException.IO_EXCEPTION;
+        BadApplicationConfigurationException exception = new BadApplicationConfigurationException("Configuration error", configException);
+        ResponseEntity<ConfigurationException> response = exceptionHandler.handle(exception);
+
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(response.getBody()));
+    }
+
+    @Test
+    public void testOreSiTechnicalExceptionSerializability() {
+        // Cas d'autorisation
+        OreSiTechnicalException authException = new OreSiTechnicalException("Auth error") {
+            public String getPackageName() {
+                return "fr.inra.oresing.domain.authorization.privilegeassessor.exception";
+            }
+        };
+        ResponseEntity<OreSiTechnicalException> authResponse = exceptionHandler.handle(authException);
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(authResponse.getBody()));
+
+        // Cas technique général
+        OreSiTechnicalException techException = new OreSiTechnicalException("Technical error");
+        ResponseEntity<OreSiTechnicalException> techResponse = exceptionHandler.handle(techException);
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(techResponse.getBody()));
+    }
+
+    @Test
+    public void testInvalidDatasetContentExceptionSerializability() {
+        List<CsvRowValidationCheckResult> errors = List.of(
+                new CsvRowValidationCheckResult(
+                        new BooleanValidationCheckResult(
+                                ValidationLevel.ERROR,
+                                "Error in row 1",
+                                Map.of("totot", "toto"),
+                                null,
+                                BooleanType.forExpression("return true", ImmutableMap.of())
+                        ),
+                        1
+                ),
+                new CsvRowValidationCheckResult(
+                        new BooleanValidationCheckResult(
+                                ValidationLevel.ERROR,
+                                "Error in row 2",
+                                Map.of("totot", "toto2"),
+                                null,
+                                BooleanType.forExpression("return false", ImmutableMap.of())
+                        ),
+                        2
+                )
+        );
+        InvalidDatasetContentException exception = new InvalidDatasetContentException(errors);
+        ResponseEntity<List<CsvRowValidationCheckResult>> response = exceptionHandler.handle(exception);
+
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(response.getBody()));
+    }
+
+    @Test
+    public void testBadBinaryFileDatasetQuerySerializability() {
+        BadBinaryFileDatasetQuery exception = new BadBinaryFileDatasetQuery("Bad binary file query");
+        ResponseEntity<String> response = exceptionHandler.handle(exception);
+
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(response.getBody()));
+    }
+
+    @Test
+    public void testBadDownloadDatasetQuerySerializability() {
+        BadDownloadDatasetQuery exception = new BadDownloadDatasetQuery("Bad download query");
+        ResponseEntity<String> response = exceptionHandler.handle(exception);
+
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(response.getBody()));
+    }
+
+    @Test
+    public void testBadFileOrUUIDQuerySerializability() {
+        BadFileOrUUIDQuery exception = new BadFileOrUUIDQuery("Bad file or UUID");
+        ResponseEntity<String> response = exceptionHandler.handle(exception);
+
+        assertDoesNotThrow(() -> objectMapper.writeValueAsString(response.getBody()));
+    }
+}
\ No newline at end of file
-- 
GitLab


From 3638d7f363fe3d18455023d464fa0d2153035e59 Mon Sep 17 00:00:00 2001
From: philippe tcheriatinsky <philippe.tcherniatinsky@inrae.fr>
Date: Fri, 28 Feb 2025 11:34:54 +0100
Subject: [PATCH 6/6] Correction test

---
 src/test/java/fr/inra/oresing/rest/TestReferencesErrors.java | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/test/java/fr/inra/oresing/rest/TestReferencesErrors.java b/src/test/java/fr/inra/oresing/rest/TestReferencesErrors.java
index e25d4b6..d7cee3a 100644
--- a/src/test/java/fr/inra/oresing/rest/TestReferencesErrors.java
+++ b/src/test/java/fr/inra/oresing/rest/TestReferencesErrors.java
@@ -75,6 +75,8 @@ public class TestReferencesErrors {
     @Autowired
     private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
     private Cookie authCookie;
+    private static CreateUserResult authUser = null;
+    private static UUID userId;
     @AfterAll
     public static void registerErrors() throws IOException {
         String errorsAsString = new ObjectMapper().writeValueAsString(responses);
@@ -88,7 +90,7 @@ public class TestReferencesErrors {
     @BeforeEach
     public void createUser() throws Exception {
         try {
-            authUser = authenticationService.createUser("poussin", "xxxxxxxx", "poussin@inrae.fr");
+            authUser = authenticationService.createUser(LOGIN, PASSWORD, EMAIL);
             userId = authUser.userId();
             setToActive(authUser.userId());
         } catch (AuthenticationFailure e) {
-- 
GitLab