diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/EingangTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/EingangTestFactory.java index 5923df23e81ce24fdcffa108627b5d94558f2747..5c50fc0b3fb528b426573e4fb44a63593de2fc74 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/EingangTestFactory.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/EingangTestFactory.java @@ -40,7 +40,7 @@ public class EingangTestFactory { public static final String SUBFORM_NAME = "kontakt"; public static final Map<String, Object> SUBFORM = Map.of(SUBFORM_FIELD_NAME, SUBFORM_FIELD_VALUE); - public static final Map<String, Object> AS_MAP = Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, SUBFORM_NAME, SUBFORM); + public static final Map<String, Object> AS_MAP = Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, NUMERIC_FIELD_NAME, NUMERIC_FIELD_VALUE, SUBFORM_NAME, SUBFORM); public static Eingang create() { return createBuilder().build(); @@ -52,8 +52,6 @@ public class EingangTestFactory { .antragsteller(AntragstellerTestFactory.create()) .header(EingangHeaderTestFactory.create()) .zustaendigeStelle(ZustaendigeStelleTestFactory.create()) - .formData(Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, - NUMERIC_FIELD_NAME, NUMERIC_FIELD_VALUE, - SUBFORM_NAME, SUBFORM)); + .formData(AS_MAP); } } \ No newline at end of file diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataExportAdjuster.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataExportAdjuster.java deleted file mode 100644 index 82c3c1524f283c4a02581b9520d2819d90bda4d3..0000000000000000000000000000000000000000 --- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataExportAdjuster.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.ozgcloud.alfa.vorgang; - -import java.util.HashMap; -import java.util.Map; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -class FormDataExportAdjuster { - - static final String VALUE_KEY = "value"; - - public static Map<String, Object> adjustFormDataForExport(Map<String, Object> formData) { - return replaceValueKeys(formData); - } - - static Map<String, Object> replaceValueKeys(Map<String, Object> formData) { - Map<String, Object> result = new HashMap<>(); - for (var entry : formData.entrySet()) { - result.put(entry.getKey(), replaceValueKeysInValue(entry.getValue())); - } - return result; - } - - @SuppressWarnings("unchecked") - private static Object replaceValueKeysInValue(Object value) { - if (!(value instanceof Map)) { - return value; - } - Map<String, Object> formData = (Map<String, Object>) value; - return containsValueKeyOnly(formData) ? - replaceValueKeysInValue(formData.get(VALUE_KEY)) : - replaceValueKeys(formData); - } - - private static boolean containsValueKeyOnly(Map<String, Object> formData) { - return formData.containsKey(VALUE_KEY) && formData.size() == 1; - } -} diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataMapper.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataMapper.java index 8ab2e778ed10968019b8c1dc67d9a9f0586692c8..04e32a6a67bb855d1d29a621748a4698df013cdd 100644 --- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataMapper.java +++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataMapper.java @@ -30,19 +30,25 @@ class FormDataMapper { private DateConverter dateConverter; public Antragsdaten toAntragsdaten(@NotNull VorgangWithEingang vorgang) { - return Optional.ofNullable(vorgang.getEingang()) - .map(Eingang::getFormData) - .map(FormDataExportAdjuster::adjustFormDataForExport) - .map(this::buildAntragsdaten) - .orElseGet(Antragsdaten::new); - } - - Antragsdaten buildAntragsdaten(Map<?, ?> formData) { var antragsdaten = new Antragsdaten(); - antragsdaten.getItem().addAll(buildItems(formData)); + antragsdaten.getItem().addAll(mapFormData(vorgang)); + antragsdaten.getItem().addAll(mapOtherData(vorgang)); return antragsdaten; } + List<AntragsdatenItemType> mapFormData(VorgangWithEingang vorgang) { + return Optional.ofNullable(vorgang.getEingang()).map(Eingang::getFormData).map(this::mapData).orElse(List.of()); + } + + List<AntragsdatenItemType> mapOtherData(VorgangWithEingang vorgang) { + return Optional.ofNullable(vorgang.getEingang()).map(Eingang::getAntragsteller).map(Antragsteller::getOtherData).map(this::mapData) + .orElse(List.of()); + } + + List<AntragsdatenItemType> mapData(Map<String, Object> data) { + return buildItems(WrappedValueExtractor.extractWrappedValues(data)); + } + List<AntragsdatenItemType> buildItems(Map<?, ?> formData) { var items = new ArrayList<AntragsdatenItemType>(); for (var formDataEntry : formData.entrySet()) { diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractor.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractor.java new file mode 100644 index 0000000000000000000000000000000000000000..12a2d36bc271932aa84defc5e7d43a0bfa2bafd9 --- /dev/null +++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractor.java @@ -0,0 +1,36 @@ +package de.ozgcloud.alfa.vorgang; + +import java.util.HashMap; +import java.util.Map; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +class WrappedValueExtractor { + + static final String WRAPPER_KEY = "value"; + + public static Map<String, Object> extractWrappedValues(Map<String, Object> formData) { + Map<String, Object> result = new HashMap<>(); + for (var entry : formData.entrySet()) { + result.put(entry.getKey(), replaceWrappedValueWithDirectValue(entry.getValue())); + } + return result; + } + + @SuppressWarnings("unchecked") + static Object replaceWrappedValueWithDirectValue(Object value) { + if (!(value instanceof Map)) { + return value; + } + Map<String, Object> formData = (Map<String, Object>) value; + return isWrappedValue(formData) ? + replaceWrappedValueWithDirectValue(formData.get(WRAPPER_KEY)) : + extractWrappedValues(formData); + } + + static boolean isWrappedValue(Map<String, Object> formData) { + return formData.containsKey(WRAPPER_KEY) && formData.size() == 1; + } +} diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceITCase.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceITCase.java index 94cb0a3ac45e052dd9fb1551e55cefbe0826d062..8116403db510a3af998bb644a0f56f2e5e810f7b 100644 --- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceITCase.java +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceITCase.java @@ -29,10 +29,21 @@ class ExportVorgangServiceITCase { class TestMapAntragsdaten { private static final Map<String, Object> FORM_DATA = Map.of( - KEY_STRING, VALUE_STRING, + KEY_STRING, VALUE_STRING + + ); + + private static final Map<String, Object> OTHER_DATA = Map.of( KEY_MAP, Map.of(KEY_COLLECTION, List.of(VALUE_INTEGER)) ); + @Test + void shouldContainSingleAntragsdatenElement() { + var vorgangType = exportVorgangService.createVorgangType(VorgangWithEingangTestFactory.create()); + + assertThat(vorgangType.getAnwendungsspezifischeErweiterungXML().getAny()).hasSize(1).first().isInstanceOf(Antragsdaten.class); + } + @Test void shouldMapSingleField() { var antragsdaten = mapToAntragsdaten(); @@ -77,17 +88,13 @@ class ExportVorgangServiceITCase { } private Antragsdaten mapToAntragsdaten() { - var erweiterungType = exportVorgangService.createVorgangType(buildVorgang()).getAnwendungsspezifischeErweiterungXML(); - - assertThat(erweiterungType.getAny()).hasSize(1).first().isInstanceOf(Antragsdaten.class); - return (Antragsdaten) erweiterungType.getAny().get(0); + var eingang = EingangTestFactory.createBuilder().formData(FORM_DATA) + .antragsteller(AntragstellerTestFactory.createBuilder().otherData(OTHER_DATA).build()) + .build(); + var vorgangWithEingang = VorgangWithEingangTestFactory.createBuilder().eingang(eingang).build(); + var vorgangType = exportVorgangService.createVorgangType(vorgangWithEingang); + return (Antragsdaten) vorgangType.getAnwendungsspezifischeErweiterungXML().getAny().get(0); } - - private VorgangWithEingang buildVorgang() { - var eingang = EingangTestFactory.createBuilder().formData(FORM_DATA).build(); - return VorgangWithEingangTestFactory.createBuilder().eingang(eingang).build(); - } - } } } \ No newline at end of file diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataExportAdjusterTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataExportAdjusterTest.java deleted file mode 100644 index 4dd12aab91f9e6e84ca5622c1a34a67ea827a6e1..0000000000000000000000000000000000000000 --- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataExportAdjusterTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package de.ozgcloud.alfa.vorgang; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import java.util.Map; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; - -public class FormDataExportAdjusterTest { - - @Nested - class TestAdjustFormDataForExport { - - private final Map<String, Object> formData = Map.of("key", "value"); - - @Test - void shouldCallReplaceValueKeys() { - try (MockedStatic<FormDataExportAdjuster> adjusterMock = mockStatic(FormDataExportAdjuster.class)) { - adjusterMock.when(() -> FormDataExportAdjuster.adjustFormDataForExport(any())).thenCallRealMethod(); - - FormDataExportAdjuster.adjustFormDataForExport(formData); - - adjusterMock.verify(() -> FormDataExportAdjuster.replaceValueKeys(formData)); - } - } - } - - @Nested - class TestReplaceValueKeys { - - @Test - void shouldPreserveValueKeyWithoutParent() { - Map<String, Object> formData = Map.of("value", "Kiel"); - - var formDataWithoutValueKeys = FormDataExportAdjuster.replaceValueKeys(formData); - - assertThat(formDataWithoutValueKeys).isEqualTo(formData); - } - - @Test - void shouldEliminateValueKeyWithoutSiblings() { - Map<String, Object> formData = Map.of("ort", Map.of("value", "Kiel")); - Map<String, Object> expected = Map.of("ort", "Kiel"); - - var formDataWithoutValueKeys = FormDataExportAdjuster.replaceValueKeys(formData); - - assertThat(formDataWithoutValueKeys).isEqualTo(expected); - } - - @Test - void shouldPreserveValueKeyIfHasSiblings() { - Map<String, Object> formData = Map.of("ort", Map.of("value", "Kiel", "value2", "Kiel")); - - var formDataWithoutValueKeys = FormDataExportAdjuster.replaceValueKeys(formData); - - assertThat(formDataWithoutValueKeys).isEqualTo(formData); - } - - @Test - void shouldPreserveNonValueKeys() { - Map<String, Object> formData = Map.of("empfangendestelle", - Map.of("value", Map.of("OrganisationseinheitenAuswahl", Map.of("value", "123456")))); - Map<String, Object> expected = Map.of("empfangendestelle", Map.of("OrganisationseinheitenAuswahl", "123456")); - - var formDataWithoutValueKeys = FormDataExportAdjuster.replaceValueKeys(formData); - - assertThat(formDataWithoutValueKeys).isEqualTo(expected); - } - } -} diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataMapperTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataMapperTest.java index 43cd844e02dc23f896233c235ff48fca4e6b00d0..76557218cfb705d40f2f8a8eeccfef4f0c68d275 100644 --- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataMapperTest.java +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataMapperTest.java @@ -1,23 +1,26 @@ package de.ozgcloud.alfa.vorgang; import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.time.ZonedDateTime; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.UUID; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullAndEmptySource; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.Spy; +import com.thedeanda.lorem.LoremIpsum; + import de.ozgcloud.alfa.common.DateConverter; import de.xoev.xdomea.AntragsdatenFieldType; import de.xoev.xdomea.AntragsdatenGroupType; @@ -40,70 +43,232 @@ class FormDataMapperTest { @Nested class TestToAntragsdaten { - @Mock - private VorgangWithEingang vorgang; + private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); + private final List<AntragsdatenFieldType> formDataItems = List.of(AntragsdatenItemTypeTestFactory.createSingleValueField(), + AntragsdatenItemTypeTestFactory.createSingleValueField()); + private final List<AntragsdatenFieldType> otherDataItems = List.of(AntragsdatenItemTypeTestFactory.createMultiValueField()); + + @Test + void shouldMapFormData() { + mockMapDataMethodsToReturnNotEmptyResults(); + + formDataMapper.toAntragsdaten(vorgang); + + verify(formDataMapper).mapFormData(vorgang); + } + + @Test + void shouldMapOtherData() { + mockMapDataMethodsToReturnNotEmptyResults(); + + formDataMapper.toAntragsdaten(vorgang); + + verify(formDataMapper).mapOtherData(vorgang); + } @Test - void shouldCallBuildAntragsdaten() { - try (MockedStatic<FormDataExportAdjuster> valueKeysRemover = mockStatic(FormDataExportAdjuster.class)) { - var vorgang = VorgangWithEingangTestFactory.create(); - Map<String, Object> formDataWithoutValueKeys = Map.of(UUID.randomUUID().toString(), "value1"); - valueKeysRemover.when(() -> FormDataExportAdjuster.adjustFormDataForExport(any())).thenReturn(formDataWithoutValueKeys); - doReturn(new Object()).when(formDataMapper).formatValue(any(), any()); + void shouldSetItemToEmptyListIfNoDataWasMapped() { + mockMapDataMethodsToReturnEmptyResults(); - formDataMapper.toAntragsdaten(vorgang); + var antragsdaten = formDataMapper.toAntragsdaten(vorgang); - verify(formDataMapper).buildAntragsdaten(formDataWithoutValueKeys); - } + assertThat(antragsdaten.getItem()).isEmpty(); } @Test - void shouldMapEingangNull() { - var Antragsdaten = formDataMapper.toAntragsdaten(vorgang); + void shouldAddMappedFormDataToAntragsdaten() { + mockMapDataMethodsToReturnNotEmptyResults(); + + var antragsdaten = formDataMapper.toAntragsdaten(vorgang); - assertThat(Antragsdaten.getItem()).isEmpty(); + assertThat(antragsdaten.getItem()).containsAll(formDataItems); } @Test - void shouldMapFormDataNull() { - var eingang = mock(Eingang.class); - when(vorgang.getEingang()).thenReturn(eingang); + void shouldAddMappedOtherDataToAntragsdaten() { + mockMapDataMethodsToReturnNotEmptyResults(); + + var antragsdaten = formDataMapper.toAntragsdaten(vorgang); - var Antragsdaten = formDataMapper.toAntragsdaten(vorgang); + assertThat(antragsdaten.getItem()).containsAll(otherDataItems); + } - assertThat(Antragsdaten.getItem()).isEmpty(); + private void mockMapDataMethodsToReturnNotEmptyResults() { + doReturn(formDataItems).when(formDataMapper).mapFormData(vorgang); + doReturn(otherDataItems).when(formDataMapper).mapOtherData(vorgang); } + private void mockMapDataMethodsToReturnEmptyResults() { + doReturn(List.of()).when(formDataMapper).mapFormData(vorgang); + doReturn(List.of()).when(formDataMapper).mapOtherData(vorgang); + } } @Nested - class TestBuildAntragsdaten { + class TestMapFormData { - private final Map<?,?> formData = EingangTestFactory.create().getFormData(); - private final List<AntragsdatenItemType> items = AntragsdatenItemTypeTestFactory.createAntragsdatenItemTypes(); + private VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); + private final List<AntragsdatenFieldType> mapDataResult = List.of(AntragsdatenItemTypeTestFactory.createSingleValueField(), + AntragsdatenItemTypeTestFactory.createSingleValueField()); + + @Test + void shouldReturnEmptyOnNullEingang() { + vorgang = VorgangWithEingangTestFactory.createBuilder().eingang(null).build(); + + var antragsdatenItemTypes = formDataMapper.mapFormData(vorgang); + + assertThat(antragsdatenItemTypes).isEmpty(); + } + + @ParameterizedTest + @NullAndEmptySource + void shouldReturnEmptyOnMissingFormData(Map<String, Object> formData) { + vorgang = VorgangWithEingangTestFactory.createBuilder() + .eingang(EingangTestFactory.createBuilder().formData(formData).build()) + .build(); + + var antragsdatenItemTypes = formDataMapper.mapFormData(vorgang); + + assertThat(antragsdatenItemTypes).isEmpty(); + } + + @Test + void shouldMapData() { + doReturn(List.of()).when(formDataMapper).mapData(EingangTestFactory.AS_MAP); + + formDataMapper.mapFormData(vorgang); + + verify(formDataMapper).mapData(EingangTestFactory.AS_MAP); + } + + @Test + void shouldReturnMappedData() { + doReturn(mapDataResult).when(formDataMapper).mapData(vorgang.getEingang().getFormData()); + + var antragsdatenItemTypes = formDataMapper.mapFormData(vorgang); + + assertThat(antragsdatenItemTypes).containsExactlyElementsOf(mapDataResult); + } + } + + @Nested + class TestMapOtherData { + + private VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); + private final List<AntragsdatenFieldType> mapDataResult = List.of(AntragsdatenItemTypeTestFactory.createSingleValueField(), + AntragsdatenItemTypeTestFactory.createSingleValueField()); + + @Test + void shouldReturnEmptyOnNullEingang() { + vorgang = VorgangWithEingangTestFactory.createBuilder().eingang(null).build(); + + var antragsdatenItemTypes = formDataMapper.mapOtherData(vorgang); + + assertThat(antragsdatenItemTypes).isEmpty(); + } + + @Test + void shouldReturnEmptyOnNullAntragsteller() { + vorgang = VorgangWithEingangTestFactory.createBuilder() + .eingang(EingangTestFactory.createBuilder().antragsteller(null).build()) + .build(); + + var antragsdatenItemTypes = formDataMapper.mapOtherData(vorgang); + + assertThat(antragsdatenItemTypes).isEmpty(); + } + + @ParameterizedTest + @NullAndEmptySource + void shouldReturnEmptyOnMissingOtherData(Map<String, Object> otherData) { + vorgang = VorgangWithEingangTestFactory.createBuilder() + .eingang(EingangTestFactory.createBuilder() + .antragsteller(AntragstellerTestFactory.createBuilder() + .otherData(otherData) + .build()) + .build()) + .build(); + + var antragsdatenItemTypes = formDataMapper.mapOtherData(vorgang); + + assertThat(antragsdatenItemTypes).isEmpty(); + } + + @Test + void shouldMapData() { + doReturn(List.of()).when(formDataMapper).mapData(AntragstellerTestFactory.OTHER_DATA); + + formDataMapper.mapOtherData(vorgang); + + verify(formDataMapper).mapData(AntragstellerTestFactory.OTHER_DATA); + } + + @Test + void shouldReturnMappedData() { + doReturn(mapDataResult).when(formDataMapper).mapData(AntragstellerTestFactory.OTHER_DATA); + + var antragsdatenItemTypes = formDataMapper.mapOtherData(vorgang); + + assertThat(antragsdatenItemTypes).containsExactlyElementsOf(mapDataResult); + } + } + + @Nested + class TestMapData { + + private final Map<String, Object> originalData = randomFormData(); + private final Map<String, Object> extractedData = randomFormData(); + private final List<AntragsdatenFieldType> mapDataResult = List.of(AntragsdatenItemTypeTestFactory.createSingleValueField(), + AntragsdatenItemTypeTestFactory.createSingleValueField()); + private MockedStatic<WrappedValueExtractor> wrappedValueExtractor; @BeforeEach void init() { - doReturn(items).when(formDataMapper).buildItems(any()); + wrappedValueExtractor = mockStatic(WrappedValueExtractor.class); + wrappedValueExtractor.when(() -> WrappedValueExtractor.extractWrappedValues(originalData)).thenReturn(extractedData); + doReturn(mapDataResult).when(formDataMapper).buildItems(extractedData); + } + + @AfterEach + void cleanup() { + wrappedValueExtractor.close(); } @Test - void shouldCallBuildItems() { - formDataMapper.buildAntragsdaten(formData); + void shouldCallWrappedValueExtractor() { + formDataMapper.mapData(originalData); + + wrappedValueExtractor.verify(() -> WrappedValueExtractor.extractWrappedValues(originalData)); + } + + @Test + void shouldCallBuildItemsWithExtractedData() { + formDataMapper.mapData(originalData); - verify(formDataMapper).buildItems(formData); + verify(formDataMapper).buildItems(extractedData); } @Test - void shouldFillItems() { - var antragsdaten = formDataMapper.buildAntragsdaten(formData); + void shouldReturnBuildItemsResult() { + var mappedData = formDataMapper.mapData(originalData); - assertThat(antragsdaten.getItem()).containsExactlyElementsOf(items); + assertThat(mappedData).isEqualTo(mapDataResult); + } + + private static Map<String, Object> randomFormData() { + return Map.of(LoremIpsum.getInstance().getWords(1), LoremIpsum.getInstance().getWords(1), + LoremIpsum.getInstance().getWords(1), LoremIpsum.getInstance().getWords(1)); } } @Nested class TestBuildItems { + + private static final String FORMDATA_KEY = "key1"; + private static final String SINGLE_VALUE = "value"; + private static final List<Object> COLLECTION_OF_VALUES = List.of("value"); + private static final Map<String, Object> FORMDATA_SUBMAP = Map.of("key2", "value"); + @Mock private AntragsdatenItemType expectedAntragsdatenItem; @@ -116,27 +281,27 @@ class FormDataMapperTest { @Test void shoulAddSubmap() { - doReturn(expectedAntragsdatenItem).when(formDataMapper).buildAntragsdatenGroup(any(), any()); + doReturn(expectedAntragsdatenItem).when(formDataMapper).buildAntragsdatenGroup(FORMDATA_KEY, FORMDATA_SUBMAP); - var items = formDataMapper.buildItems(Map.of("key", Map.of("key", "value"))); + var items = formDataMapper.buildItems(Map.of(FORMDATA_KEY, FORMDATA_SUBMAP)); assertThat(items).hasSize(1).first().isEqualTo(expectedAntragsdatenItem); } @Test void shouldAddCollection() { - doReturn(expectedAntragsdatenItem).when(formDataMapper).buildMultiValueField(any(), any()); + doReturn(expectedAntragsdatenItem).when(formDataMapper).buildMultiValueField(FORMDATA_KEY, COLLECTION_OF_VALUES); - var items = formDataMapper.buildItems(Map.of("key", List.of("value"))); + var items = formDataMapper.buildItems(Map.of(FORMDATA_KEY, COLLECTION_OF_VALUES)); assertThat(items).hasSize(1).first().isEqualTo(expectedAntragsdatenItem); } @Test void shouldAddSingleValue() { - doReturn(expectedAntragsdatenItem).when(formDataMapper).buildSingleValueField(any(), any()); + doReturn(expectedAntragsdatenItem).when(formDataMapper).buildSingleValueField(FORMDATA_KEY, SINGLE_VALUE); - var items = formDataMapper.buildItems(Map.of("key", "value")); + var items = formDataMapper.buildItems(Map.of(FORMDATA_KEY, SINGLE_VALUE)); assertThat(items).hasSize(1).first().isEqualTo(expectedAntragsdatenItem); } @@ -146,12 +311,13 @@ class FormDataMapperTest { class TestBuildAntragsdatenGroup { private static final String NAME = "name"; - private static final Map<String, Object> FORMDATA_SUBMAP = Map.of("key", "value"); + private static final String FORMDATA_SUBMAP_VALUE = "value"; + private static final Map<String, Object> FORMDATA_SUBMAP = Map.of("key", FORMDATA_SUBMAP_VALUE); private final List<AntragsdatenItemType> items = AntragsdatenItemTypeTestFactory.createAntragsdatenItemTypes(); @Test void shouldSetName() { - doReturn(new Object()).when(formDataMapper).formatValue(any(), any()); + mockFormatValue(); var antragsdatenGroup = formDataMapper.buildAntragsdatenGroup(NAME, FORMDATA_SUBMAP); @@ -160,7 +326,7 @@ class FormDataMapperTest { @Test void shouldSetItems() { - doReturn(items).when(formDataMapper).buildItems(any()); + doReturn(items).when(formDataMapper).buildItems(FORMDATA_SUBMAP); var antragsdatenGroup = (AntragsdatenGroupType) formDataMapper.buildAntragsdatenGroup(NAME, FORMDATA_SUBMAP); @@ -169,12 +335,17 @@ class FormDataMapperTest { @Test void shouldCallBuildItems() { - doReturn(new Object()).when(formDataMapper).formatValue(any(), any()); + mockFormatValue(); formDataMapper.buildAntragsdatenGroup(NAME, FORMDATA_SUBMAP); verify(formDataMapper).buildItems(FORMDATA_SUBMAP); } + + private void mockFormatValue() { + when(datatypeMapper.from(FORMDATA_SUBMAP_VALUE)).thenReturn(DatatypeType.STRING); + doReturn(new Object()).when(formDataMapper).formatValue(DatatypeType.STRING, FORMDATA_SUBMAP_VALUE); + } } @Nested @@ -185,7 +356,7 @@ class FormDataMapperTest { @Test void shouldSetName() { - when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING); + when(datatypeMapper.from(FORMDATA_COLLECTION)).thenReturn(DatatypeType.STRING); var antragsdatenMultiValueFieldType = formDataMapper.buildMultiValueField(NAME, FORMDATA_COLLECTION); @@ -194,7 +365,7 @@ class FormDataMapperTest { @Test void shouldSetType() { - when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING); + when(datatypeMapper.from(FORMDATA_COLLECTION)).thenReturn(DatatypeType.STRING); var antragsdatenMultiValueFieldType = (AntragsdatenFieldType) formDataMapper.buildMultiValueField(NAME, FORMDATA_COLLECTION); @@ -203,8 +374,8 @@ class FormDataMapperTest { @Test void shouldSetValue() { - when(datatypeMapper.from(any())).thenReturn(DatatypeType.INTEGER); var formData = List.of(1, 2); + when(datatypeMapper.from(formData)).thenReturn(DatatypeType.INTEGER); var antragsdatenMultiValueFieldType = (AntragsdatenMultiValueFieldType) formDataMapper.buildMultiValueField(NAME, formData); @@ -213,7 +384,7 @@ class FormDataMapperTest { @Test void shouldCallFormatValue() { - when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING); + when(datatypeMapper.from(FORMDATA_COLLECTION)).thenReturn(DatatypeType.STRING); formDataMapper.buildMultiValueField(NAME, FORMDATA_COLLECTION); @@ -229,8 +400,7 @@ class FormDataMapperTest { @Test void shouldSetName() { - doReturn(new Object()).when(formDataMapper).formatValue(any(), any()); - + mockFormatValue(); var antragsdatenSingleValueFieldType = formDataMapper.buildSingleValueField(NAME, FORMDATA_VALUE); assertThat(antragsdatenSingleValueFieldType.getName()).isEqualTo(NAME); @@ -238,7 +408,7 @@ class FormDataMapperTest { @Test void shouldSetType() { - when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING); + when(datatypeMapper.from(FORMDATA_VALUE)).thenReturn(DatatypeType.STRING); var antragsdatenSingleValueFieldType = (AntragsdatenFieldType) formDataMapper.buildSingleValueField(NAME, FORMDATA_VALUE); @@ -247,7 +417,7 @@ class FormDataMapperTest { @Test void shouldSetValue() { - doReturn(FORMDATA_VALUE).when(formDataMapper).formatValue(any(), any()); + mockFormatValue(); var antragsdatenSingleValueFieldType = (AntragsdatenSingleValueFieldType) formDataMapper.buildSingleValueField(NAME, FORMDATA_VALUE); @@ -261,15 +431,19 @@ class FormDataMapperTest { verify(formDataMapper, never()).formatValue(DatatypeType.STRING, null); } - @Test void shouldCallFormatValue() { - when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING); + when(datatypeMapper.from(FORMDATA_VALUE)).thenReturn(DatatypeType.STRING); formDataMapper.buildSingleValueField(NAME, FORMDATA_VALUE); verify(formDataMapper).formatValue(DatatypeType.STRING, FORMDATA_VALUE); } + + private void mockFormatValue() { + when(datatypeMapper.from(FORMDATA_VALUE)).thenReturn(DatatypeType.STRING); + doReturn(FORMDATA_VALUE).when(formDataMapper).formatValue(DatatypeType.STRING, FORMDATA_VALUE); + } } @Nested diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractorITCase.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractorITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..2235bb23d85ac3e6a812a49aa88b2ec107a32ea7 --- /dev/null +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractorITCase.java @@ -0,0 +1,55 @@ +package de.ozgcloud.alfa.vorgang; + +import static de.ozgcloud.alfa.vorgang.WrappedValueExtractor.*; +import static org.assertj.core.api.Assertions.*; + +import java.util.Map; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +public class WrappedValueExtractorITCase { + + @Nested + class TestExtractWrappedValues { + + @Test + void shouldPreserveWrapperKeyWithoutParent() { + Map<String, Object> formData = Map.of(WRAPPER_KEY, "Kiel"); + + var formDataWithoutValueKeys = WrappedValueExtractor.extractWrappedValues(formData); + + assertThat(formDataWithoutValueKeys).isEqualTo(formData); + } + + @Test + void shouldEliminateWrapperKeyWithoutSiblings() { + Map<String, Object> formData = Map.of("ort", Map.of(WRAPPER_KEY, "Kiel")); + Map<String, Object> expected = Map.of("ort", "Kiel"); + + var formDataWithoutValueKeys = WrappedValueExtractor.extractWrappedValues(formData); + + assertThat(formDataWithoutValueKeys).isEqualTo(expected); + } + + @Test + void shouldPreserveWrapperKeyIfHasSiblings() { + Map<String, Object> formData = Map.of("ort", Map.of(WRAPPER_KEY, "Kiel", "value2", "Kiel")); + + var formDataWithoutValueKeys = WrappedValueExtractor.extractWrappedValues(formData); + + assertThat(formDataWithoutValueKeys).isEqualTo(formData); + } + + @Test + void shouldPreserveNonWrapperKeys() { + Map<String, Object> formData = Map.of("empfangendestelle", + Map.of(WRAPPER_KEY, Map.of("OrganisationseinheitenAuswahl", Map.of(WRAPPER_KEY, "123456")))); + Map<String, Object> expected = Map.of("empfangendestelle", Map.of("OrganisationseinheitenAuswahl", "123456")); + + var formDataWithoutValueKeys = WrappedValueExtractor.extractWrappedValues(formData); + + assertThat(formDataWithoutValueKeys).isEqualTo(expected); + } + } +} diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..419c371d6aaf4f8a75904ec986814ffa4187881b --- /dev/null +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractorTest.java @@ -0,0 +1,176 @@ +package de.ozgcloud.alfa.vorgang; + +import static de.ozgcloud.alfa.vorgang.WrappedValueExtractor.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.Map; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.MockedStatic; + +public class WrappedValueExtractorTest { + + @Nested + class TestExtractWrappedValues { + + private static final String KEY1 = "key1"; + private static final String KEY2 = "key2"; + private static final String KEY3 = "key3"; + + @Captor + private ArgumentCaptor<Object> valueCaptor; + private final Map<String, Object> originalData = Map.of(KEY1, "value1", KEY2, true, KEY3, 100); + private final Map<String, Object> extractedData = Map.of(KEY1, "extracted1", KEY2, "extracted2", KEY3, "extracted3"); + + @Test + void shouldCallReplaceWrappedValueWithDirectValue() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + + WrappedValueExtractor.extractWrappedValues(originalData); + + wrappedValueExtractor.verify(() -> WrappedValueExtractor.replaceWrappedValueWithDirectValue(valueCaptor.capture()), times( + originalData.size())); + assertThat(valueCaptor.getAllValues()).containsExactlyElementsOf(originalData.values()); + } + } + + @Test + void shouldReturnMapWithReplacedValues() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + wrappedValueExtractor.when(() -> WrappedValueExtractor.replaceWrappedValueWithDirectValue(originalData.get(KEY1))).thenReturn(extractedData.get(KEY1)); + wrappedValueExtractor.when(() -> WrappedValueExtractor.replaceWrappedValueWithDirectValue(originalData.get(KEY2))).thenReturn(extractedData.get(KEY2)); + wrappedValueExtractor.when(() -> WrappedValueExtractor.replaceWrappedValueWithDirectValue(originalData.get(KEY3))).thenReturn(extractedData.get(KEY3)); + + var result = WrappedValueExtractor.extractWrappedValues(originalData); + + assertThat(result).isEqualTo(extractedData); + } + } + + private void unmockMethodUnderTest(MockedStatic<WrappedValueExtractor> wrappedValueExtractor) { + wrappedValueExtractor.when(() -> WrappedValueExtractor.extractWrappedValues(any())).thenCallRealMethod(); + } + } + + @Nested + class TestReplaceWrappedValueWithDirectValue { + + private final String simpleValue = "simple value"; + private final Map<String, Object> mapValue = Map.of("key1", "value1", "key2", "value2"); + private final Map<String, Object> wrappedValue = Map.of(WRAPPER_KEY, "value1"); + + @Test + void shouldReturnValue() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + + var result = WrappedValueExtractor.replaceWrappedValueWithDirectValue(simpleValue); + + assertThat(result).isEqualTo(simpleValue); + } + } + + @Test + void shouldCallIsWrappedValue() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + + WrappedValueExtractor.replaceWrappedValueWithDirectValue(mapValue); + + wrappedValueExtractor.verify(() -> WrappedValueExtractor.isWrappedValue(mapValue)); + } + } + + @Test + void shouldCallItself() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + wrappedValueExtractor.when(() -> WrappedValueExtractor.isWrappedValue(wrappedValue)).thenReturn(true); + + WrappedValueExtractor.replaceWrappedValueWithDirectValue(wrappedValue); + + wrappedValueExtractor.verify(() -> WrappedValueExtractor.replaceWrappedValueWithDirectValue(wrappedValue.get(WRAPPER_KEY))); + } + } + + @Test + void shouldReturnResultOfCallingItself() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + wrappedValueExtractor.when(() -> WrappedValueExtractor.isWrappedValue(wrappedValue)).thenReturn(true); + + var result = WrappedValueExtractor.replaceWrappedValueWithDirectValue(wrappedValue); + + assertThat(result).isEqualTo(wrappedValue.get(WRAPPER_KEY)); + } + } + + @Test + void shouldCallExtractWrappedValues() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + wrappedValueExtractor.when(() -> WrappedValueExtractor.isWrappedValue(mapValue)).thenReturn(false); + + WrappedValueExtractor.replaceWrappedValueWithDirectValue(mapValue); + + wrappedValueExtractor.verify(() -> WrappedValueExtractor.extractWrappedValues(mapValue)); + } + } + + @Test + void shouldReturnResultOfExtractWrappedValues() { + final Map<String, Object> extractVrappedValuesResult = Map.of("resultKey", "resultValue"); + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + wrappedValueExtractor.when(() -> WrappedValueExtractor.isWrappedValue(mapValue)).thenReturn(false); + wrappedValueExtractor.when(() -> WrappedValueExtractor.extractWrappedValues(any())).thenReturn(extractVrappedValuesResult); + + var result = WrappedValueExtractor.replaceWrappedValueWithDirectValue(mapValue); + + assertThat(result).isEqualTo(extractVrappedValuesResult); + } + } + + private void unmockMethodUnderTest(MockedStatic<WrappedValueExtractor> wrappedValueExtractor) { + wrappedValueExtractor.when(() -> WrappedValueExtractor.replaceWrappedValueWithDirectValue(any())).thenCallRealMethod(); + } + } + + @Nested + class TestIsWrappedValue { + + @Test + void shouldReturnTrueIfWrapped() { + var result = WrappedValueExtractor.isWrappedValue(Map.of(WRAPPER_KEY, "value1")); + + assertThat(result).isTrue(); + } + + @Test + void shouldReturnFalseIfHasMultipleEntries() { + var result = WrappedValueExtractor.isWrappedValue(Map.of(WRAPPER_KEY, "value1", "key2", "value2")); + + assertThat(result).isFalse(); + } + + @Test + void shouldReturnFalseIfNotWrapped() { + var result = WrappedValueExtractor.isWrappedValue(Map.of("key1", "value1")); + + assertThat(result).isFalse(); + } + + @Test + void shouldReturnFalseIfEmpty() { + var result = WrappedValueExtractor.isWrappedValue(Map.of()); + + assertThat(result).isFalse(); + } + } +}