diff --git a/Jenkinsfile b/Jenkinsfile index 23cf53a8e0ac1221c26bbe9964ccc87e5ccd836a..a143bcf648a7f2add38b2f1467d90d2b59d06b8e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -47,7 +47,7 @@ pipeline { sh 'xmlstarlet ed --pf -L -N w="http://maven.apache.org/POM/4.0.0" -u "//w:project/w:properties/w:maven.compiler.source" -v 11 vorgang-manager/vorgang-manager-interface/pom.xml' sh 'xmlstarlet ed --pf -L -N w="http://maven.apache.org/POM/4.0.0" -u "//w:project/w:properties/w:maven.compiler.target" -v 11 vorgang-manager/vorgang-manager-interface/pom.xml' - sh 'mvn -f vorgang-manager/vorgang-manager-interface -s $MAVEN_SETTINGS -Djava.version=11 install' + sh 'mvn -f vorgang-manager/vorgang-manager-interface -s $MAVEN_SETTINGS --no-transfer-progress -Djava.version=11 install' } } } @@ -57,7 +57,7 @@ pipeline { steps { configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) { sh 'mvn --version' - sh 'mvn -f eingang-manager/formcycle-adapter/formcycle-adapter-interface -s $MAVEN_SETTINGS -Djava.version=11 install' + sh 'mvn --no-transfer-progress -f eingang-manager/formcycle-adapter/formcycle-adapter-interface -s $MAVEN_SETTINGS -Djava.version=11 install' } } } @@ -69,7 +69,7 @@ pipeline { } configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) { sh 'mvn --version' - sh 'mvn -s $MAVEN_SETTINGS -P ci-build clean install -Dmaven.wagon.http.retryHandler.count=3' + sh 'mvn --no-transfer-progress -s $MAVEN_SETTINGS -P ci-build clean install -Dmaven.wagon.http.retryHandler.count=3' script { if (env.BRANCH_NAME == 'master') { @@ -110,7 +110,7 @@ pipeline { FAILED_STAGE = env.STAGE_NAME } configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) { - sh 'mvn -s $MAVEN_SETTINGS -DskipTests deploy -Dmaven.wagon.http.retryHandler.count=3' + sh 'mvn --no-transfer-progress -s $MAVEN_SETTINGS -DskipTests deploy -Dmaven.wagon.http.retryHandler.count=3' } } } @@ -129,7 +129,7 @@ pipeline { configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) { sh 'mvn --version' - sh 'mvn -s $MAVEN_SETTINGS -P ci-build fc-deploy:deploy -DfcDeployUrl="https://formcycle.dev.ozg-sh.de/formcycle" -DfcDeployClientId="2" -DfcDeployToken=adminhase23 -DskipTests=true -Dmaven.wagon.http.retryHandler.count=3' + sh 'mvn --no-transfer-progress -s $MAVEN_SETTINGS -P ci-build fc-deploy:deploy -DfcDeployUrl="https://formcycle.dev.ozg-sh.de/formcycle" -DfcDeployClientId="2" -DfcDeployToken=adminhase23 -DskipTests=true -Dmaven.wagon.http.retryHandler.count=3' } } post { diff --git a/pom.xml b/pom.xml index e16eb694a5b52e4f75d9a1994af0e7b9d7097b9a..9e9338347ed3d86c51fc34ef0f5c37eb2e1e83ee 100644 --- a/pom.xml +++ b/pom.xml @@ -15,15 +15,15 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- Version of FORMCYCLE to built against. --> - <xfc.version>8.1.0</xfc.version> - <fc-server-maven-plugin.version>8.0.3</fc-server-maven-plugin.version> + <xfc.version>8.1.2</xfc.version> + <fc-server-maven-plugin.version>8.1.0</fc-server-maven-plugin.version> <fc-deploy-plugin-maven-plugin.version>8.0.1</fc-deploy-plugin-maven-plugin.version> - <formcycle-adapter-interface.version>2.6.0</formcycle-adapter-interface.version> - <lombok.version>1.18.30</lombok.version> - <junit-jupiter.version>5.10.1</junit-jupiter.version> - <mockito.version>5.8.0</mockito.version> - <assertj.version>3.25.0</assertj.version> + <formcycle-adapter-interface.version>2.10.0-SNAPSHOT</formcycle-adapter-interface.version> + <lombok.version>1.18.32</lombok.version> + <junit-jupiter.version>5.10.2</junit-jupiter.version> + <mockito.version>5.12.0</mockito.version> + <assertj.version>3.26.0</assertj.version> <htmlcleaner.version>2.29</htmlcleaner.version> <!-- Maven plugin versions --> diff --git a/release-notes.md b/release-notes.md index dd12fa2dbf5edc64c262e798775a958bef7e523f..5c4f844ea7a3c73ce81b0e6e163cdbce85e3cb6b 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,5 +1,8 @@ # Version 2.5.0 +- Wenn im Formular Anhänge hochgeladen wurden, aber keine Dateien gefunden wurden, wird eine Warnung mit dem Fehlercode + MISSING_ATTACHMENTS und einer entsprechenden Nachricht protokolliert. + # Version 2.4.0 - Flexibles Einbetten des AKDB-Templates in die OZG Cloud Plugin. Ab diese Version kann das AKDB-Template, das zur diff --git a/src/main/java/de/ozgcloud/formcycle/OzgPluginExecutor.java b/src/main/java/de/ozgcloud/formcycle/OzgPluginExecutor.java index 7bb4cb98d0af20941e506dd8d25e45373c0d4ed5..a7b0ab2d1c3be9d2d10555bc2c591e0e4ee2d22d 100644 --- a/src/main/java/de/ozgcloud/formcycle/OzgPluginExecutor.java +++ b/src/main/java/de/ozgcloud/formcycle/OzgPluginExecutor.java @@ -22,23 +22,20 @@ */ package de.ozgcloud.formcycle; -import static java.util.Objects.*; - -import java.util.EnumMap; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.function.Predicate; import java.util.function.Supplier; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import de.ozgcloud.eingang.formcycle.FormCycleConfirmationResponse; import de.ozgcloud.formcycle.attachment.AttachmentMapper; -import de.ozgcloud.formcycle.attachment.AttachmentType; import de.ozgcloud.formcycle.attachment.FormcycleAttachment; import de.ozgcloud.formcycle.errorhandling.OzgPluginSoftError; import de.ozgcloud.formcycle.errorhandling.Warning; +import de.ozgcloud.formcycle.formdata.FormData; import de.ozgcloud.formcycle.formdata.OzgCloudFormDataMapper; import de.ozgcloud.formcycle.formdata.PluginFormDataAdapter; import de.xima.fc.entities.Attachment; @@ -57,36 +54,56 @@ public final class OzgPluginExecutor { public ExecutionResult execute() { LOG.debug("Executing plugin WorkflowElementNodePlugin"); - var formData = pluginFormDataAdapter.readFormData(); - var resultBuilder = ExecutionResult.builder(); - formData.getWarnings().forEach(resultBuilder::warning); - var attachments = getAttachedFiles(formData.getAttachmentUuids()); - if (isNull(attachments.get(AttachmentType.REPRESENTATION))) { - resultBuilder.warning( - buildWarning("Representation is missing. Ensure workflow is configured to attach form view to form data.")); - } + var formData = addRepresentations(pluginFormDataAdapter.readFormData()); + formData = addAttachments(formData); + return buildExecutionResult(sendFormData(formData), formData); + } - var formcycleFormData = ozgCloudFormDataMapper.map(formData); - var formCycleConfirmationResponse = ozgHttpClient.send(formcycleFormData, attachments.get(AttachmentType.ATTACHMENT), - attachments.get(AttachmentType.REPRESENTATION)); - LOG.debug("Formcycle adapter response: {}", formCycleConfirmationResponse); + FormData addRepresentations(FormData formData) { + var representations = getAttachedFiles(attachmentUuid -> !formData.getAttachmentUuids().contains(attachmentUuid)); + if (representations.isEmpty()) { + return formData.toBuilder().warning(buildMissingRepresentationsWarning(formData.getRequestId())).build(); + } + return formData.toBuilder().representations(representations).build(); + } - return resultBuilder.vorgangnummer(formCycleConfirmationResponse.getVorgangNummer()).build(); + Warning buildMissingRepresentationsWarning(String requestId) { + return buildWarning(OzgPluginSoftError.MISSING_REPRESENTATION, + String.format("Representation is missing. Ensure workflow is configured to attach form view to form data. (Request ID: %s)", + requestId)); } - Map<AttachmentType, Set<FormcycleAttachment>> getAttachedFiles(Set<String> uploadFieldUuids) { - var resultMap = new EnumMap<AttachmentType, Set<FormcycleAttachment>>(AttachmentType.class); - for (Attachment attachment : attachmentsSupplier.get()) { - if (uploadFieldUuids.contains(attachment.getUUID())) { - resultMap.computeIfAbsent(AttachmentType.ATTACHMENT, e -> new HashSet<>()).add(attachmentMapper.map(attachment)); - continue; - } - resultMap.computeIfAbsent(AttachmentType.REPRESENTATION, e -> new HashSet<>()).add(attachmentMapper.map(attachment)); + FormData addAttachments(FormData formData) { + if (formData.getAttachmentUuids().isEmpty()) { + return formData; + } + var attachments = getAttachedFiles(formData.getAttachmentUuids()::contains); + if (attachments.isEmpty()) { + return formData.toBuilder().warning(buildMissingAttachmentsWarning(formData.getRequestId())).build(); } - return resultMap; + return formData.toBuilder().attachments(attachments).build(); + } + + List<FormcycleAttachment> getAttachedFiles(Predicate<String> attachmentUuidFilter) { + return attachmentsSupplier.get().stream().filter(attachment -> attachmentUuidFilter.test(attachment.getUUID())).map(attachmentMapper::map) + .collect(Collectors.toList()); + } + + Warning buildMissingAttachmentsWarning(String requestId) { + return buildWarning(OzgPluginSoftError.MISSING_ATTACHMENTS, + String.format("Attachments uploaded in the form were not included in the form data. (RequestId: %s)", requestId)); + } + + private Warning buildWarning(OzgPluginSoftError warningCode, String message) { + return Warning.builder().errorCode(warningCode).message(message).build(); + } + + FormCycleConfirmationResponse sendFormData(FormData formData) { + return ozgHttpClient.send(ozgCloudFormDataMapper.map(formData), formData.getAttachments(), formData.getRepresentations()); } - Warning buildWarning(String message) { - return Warning.builder().errorCode(OzgPluginSoftError.MISSING_REPRESENTATION).message(message).build(); + ExecutionResult buildExecutionResult(FormCycleConfirmationResponse response, FormData formData) { + LOG.debug("Formcycle adapter response: {}", response); + return ExecutionResult.builder().vorgangnummer(response.getVorgangNummer()).warnings(formData.getWarnings()).build(); } } diff --git a/src/main/java/de/ozgcloud/formcycle/errorhandling/OzgPluginSoftError.java b/src/main/java/de/ozgcloud/formcycle/errorhandling/OzgPluginSoftError.java index 89a7c086735893b3a77b311504bcb0ed6b569a00..6536c2a00aa81f9c2ed1595b0aaee1a2328e93f0 100644 --- a/src/main/java/de/ozgcloud/formcycle/errorhandling/OzgPluginSoftError.java +++ b/src/main/java/de/ozgcloud/formcycle/errorhandling/OzgPluginSoftError.java @@ -31,9 +31,11 @@ package de.ozgcloud.formcycle.errorhandling; */ public enum OzgPluginSoftError { - /** Indicates that representation of a formular was not attached to form data */ - MISSING_REPRESENTATION, - /** Indicates that user connected the formular with a service konto and it supply an unexpected trust level value */ - UNEXPECTED_TRUST_LEVEL + /** Indicates that representation of a formular was not attached to form data */ + MISSING_REPRESENTATION, + /** Indicates that the attachments uploaded in the form were not included in the form data. */ + MISSING_ATTACHMENTS, + /** Indicates that user connected the formular with a service konto and it supply an unexpected trust level value */ + UNEXPECTED_TRUST_LEVEL } diff --git a/src/main/java/de/ozgcloud/formcycle/formdata/FormData.java b/src/main/java/de/ozgcloud/formcycle/formdata/FormData.java index fc31fca5bf5e1ebb4c2ffef8af3dc42509c71376..0f9b306bf5d5acf15fbc2766ece3b89f1cff9512 100644 --- a/src/main/java/de/ozgcloud/formcycle/formdata/FormData.java +++ b/src/main/java/de/ozgcloud/formcycle/formdata/FormData.java @@ -26,28 +26,39 @@ package de.ozgcloud.formcycle.formdata; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.UUID; +import de.ozgcloud.formcycle.attachment.FormcycleAttachment; import de.ozgcloud.formcycle.errorhandling.Warning; import lombok.Builder; import lombok.Getter; import lombok.Singular; @Getter -@Builder +@Builder(toBuilder = true) public class FormData { + private final String requestId = UUID.randomUUID().toString(); + private long formId; private String organisationsEinheitId; private String formName; private ServiceKonto serviceKonto; + @Singular private Set<String> attachmentNames; + @Singular private Set<String> attachmentUuids; private List<FormNode> fieldData; + @Singular + private List<FormcycleAttachment> attachments; + @Singular + private List<FormcycleAttachment> representations; + @Singular private List<Warning> warnings; diff --git a/src/main/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapper.java b/src/main/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapper.java index b0a47fa1efefb0acc1872622367758d2d7b63d83..abca97a7b51db26e2569d14b944a222948de313a 100644 --- a/src/main/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapper.java +++ b/src/main/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapper.java @@ -123,6 +123,8 @@ public class OzgCloudFormDataMapper { FormCycleFormHeader buildHeader(FormData formData) { FormCycleFormHeader.Builder builder = FormCycleFormHeader.newBuilder() + .setRequestId(formData.getRequestId()) + .setFormId(Long.toString(formData.getFormId())) .setReceivedAt(ZonedDateTime.now().toString()) .setOrganisationsEinheitId(formData.getOrganisationsEinheitId()); Optional.ofNullable(formData.getFormName()).ifPresent(builder::setFormName); diff --git a/src/main/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapter.java b/src/main/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapter.java index 4361bf1197872d73bbf78f1934cae77585fac2d0..bbb9fbd22c6a7b9c87cc3d76d0b86a16f83d2688 100644 --- a/src/main/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapter.java +++ b/src/main/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapter.java @@ -68,8 +68,8 @@ public class PluginFormDataAdapter { var formFields = buildFormData(); Set<String> uploadFieldNames = getUploadFieldNames(); - var formDataBuilder = FormData.builder() + .formId(environmentData.getProject().getId()) .formName(getFormName()) .organisationsEinheitId(organisationsEinheitId) .fieldData(formFields) diff --git a/src/main/resources/WEB-INF/properties/i18n_de.properties b/src/main/resources/WEB-INF/properties/i18n_de.properties index 951c16bbc7e9c30f1c5d26846baf169f0bec7da8..43c9385bb8867ff78cd0bb08d470119001382362 100644 --- a/src/main/resources/WEB-INF/properties/i18n_de.properties +++ b/src/main/resources/WEB-INF/properties/i18n_de.properties @@ -13,6 +13,7 @@ de.ozgcloud.formcycle.OzgCloudPlugin.errVal.OZGCLOUD_REQUEST_FAILED.exceptionId # Soft Errors de.ozgcloud.formcycle.OzgCloudPlugin.softerrcode.MISSING_REPRESENTATION = Warnung Code, wenn Formular Representation nicht angeh�ngt werden konnte. +de.ozgcloud.formcycle.OzgCloudPlugin.softerrcode.MISSING_ATTACHMENTS=Warnung Code, wenn im Formular hochgeladene Anh�nge nicht gefunden worden sind. de.ozgcloud.formcycle.OzgCloudPlugin.softerrcode.UNEXPECTED_TRUST_LEVEL = Warnung Code, wenn das Vertrauensniveau der BayernID Verbindung einen unerwarteten Wert hat oder leer ist. OzgPluginWorkflowNodeProperties.section_settings = Einstellungen diff --git a/src/test/java/de/ozgcloud/formcycle/OzgPluginExecutorTest.java b/src/test/java/de/ozgcloud/formcycle/OzgPluginExecutorTest.java index 9e6a6578205823a1175bacc0675b2ee4cfd36527..6b0269def717eff88ad3b6852107350171ab72de 100644 --- a/src/test/java/de/ozgcloud/formcycle/OzgPluginExecutorTest.java +++ b/src/test/java/de/ozgcloud/formcycle/OzgPluginExecutorTest.java @@ -30,6 +30,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; +import java.util.function.Predicate; import java.util.function.Supplier; import org.junit.jupiter.api.BeforeEach; @@ -45,13 +47,13 @@ import org.mockito.Spy; import de.ozgcloud.eingang.formcycle.FormCycleConfirmationResponse; import de.ozgcloud.eingang.formcycle.FormCycleFormData; import de.ozgcloud.formcycle.attachment.AttachmentMapper; -import de.ozgcloud.formcycle.attachment.AttachmentType; import de.ozgcloud.formcycle.attachment.FormcycleAttachment; import de.ozgcloud.formcycle.attachment.FormcycleAttachmentTestFactory; import de.ozgcloud.formcycle.errorhandling.NodeThrewExceptionFactory; import de.ozgcloud.formcycle.errorhandling.OzgPluginSoftError; import de.ozgcloud.formcycle.errorhandling.Warning; import de.ozgcloud.formcycle.formdata.FormData; +import de.ozgcloud.formcycle.formdata.FormDataTestFactory; import de.ozgcloud.formcycle.formdata.OzgCloudFormDataMapper; import de.ozgcloud.formcycle.formdata.PluginFormDataAdapter; import de.xima.fc.entities.Attachment; @@ -59,6 +61,8 @@ import lombok.SneakyThrows; class OzgPluginExecutorTest { + private final static FormData FORM_DATA = FormDataTestFactory.create(); + @Spy @InjectMocks private OzgPluginExecutor executor; @@ -81,120 +85,206 @@ class OzgPluginExecutorTest { @Nested class TestExecution { - private static final String VORGANGS_NUMMER = "12345"; - @Mock private FormCycleConfirmationResponse response; @Mock - private FormData formData; + private ExecutionResult executionResult; @Mock - private Warning warning; - - @Captor - private ArgumentCaptor<List<FormcycleAttachment>> attachmentsCapture; + private FormData formDataWithRepresentations; + @Mock + private FormData formDataWithAttachments; @SneakyThrows @BeforeEach void setup() { - when(response.getVorgangNummer()).thenReturn(VORGANGS_NUMMER); when(ozgHttpClient.send(any(), any(), any())).thenReturn(response); - when(pluginFormDataAdapter.readFormData()).thenReturn(formData); + when(pluginFormDataAdapter.readFormData()).thenReturn(FORM_DATA); + doReturn(formDataWithRepresentations).when(executor).addRepresentations(any()); + doReturn(formDataWithAttachments).when(executor).addAttachments(any()); + doReturn(executionResult).when(executor).buildExecutionResult(any(), any()); } - @Nested - class TestMapping { + @Test + void shouldCallPluginFormDataAdapter() { + executor.execute(); + + verify(pluginFormDataAdapter).readFormData(); + } - @BeforeEach - void setup() { - when(attachmentSupplier.get()).thenReturn(List.of()); - } + @Test + void shouldCallAddRepresentations() { + executor.execute(); - @SneakyThrows - @Test - void shouldExtractAsGrpc() { - executor.execute(); + verify(executor).addRepresentations(FORM_DATA); + } - verify(ozgCloudFormDataMapper).map(formData); - } + @Test + void shouldCallAddAttachments() { + executor.execute(); - @SneakyThrows - @Test - void shouldCreateSuccessResult() { - var executionResult = executor.execute(); + verify(executor).addAttachments(formDataWithRepresentations); + } - assertThat(executionResult.getVorgangnummer()).isEqualTo(VORGANGS_NUMMER); - } + @Test + void shouldCallSendFormData() { + executor.execute(); - @Test - void shouldAddWarnings() { - when(formData.getWarnings()).thenReturn(List.of(warning)); + verify(executor).sendFormData(formDataWithAttachments); + } - var executionResult = executor.execute(); + @Test + void shouldCallBuildExecutionResult() { + executor.execute(); - assertThat(executionResult.getWarnings()).contains(warning); - } + verify(executor).buildExecutionResult(response, formDataWithAttachments); } - @Nested - @DisplayName("Send data") - class TestSendData { + @Test + void shouldReturnExecutionResult() { + var result = executor.execute(); - @Mock - private FormCycleFormData formcycleFormData; + assertThat(result).isSameAs(executionResult); + } + } - @Captor - private ArgumentCaptor<Set<FormcycleAttachment>> attachmentsCapture; + @Nested + class TestAddRepresentations { + + @Mock + private Warning warning; + + @Captor + private ArgumentCaptor<Predicate<String>> filterPredicateCapture; + + private final FormData formData = FormDataTestFactory.createBuilder().clearRepresentations().build(); - @SneakyThrows - @BeforeEach - void setup() { - when(ozgCloudFormDataMapper.map(any())).thenReturn(formcycleFormData); - } + @Test + void shouldCallGetAttachedFiles() { + doReturn(List.of(FormcycleAttachmentTestFactory.create())).when(executor).getAttachedFiles(any()); - @SneakyThrows - @Test - void shouldSendFormData() { - when(attachmentSupplier.get()).thenReturn(List.of()); + executor.addRepresentations(formData); + + verify(executor).getAttachedFiles(filterPredicateCapture.capture()); + assertThat(filterPredicateCapture.getValue().test(FormDataTestFactory.ATTACHMENT_UUID)).isFalse(); + } - executor.execute(); + @Test + void shouldSetRepresentations() { + var representation = FormcycleAttachmentTestFactory.create(); + doReturn(List.of(representation)).when(executor).getAttachedFiles(any()); + + var result = executor.addRepresentations(formData); + + assertThat(result.getRepresentations()).hasSize(1).first().isEqualTo(representation); + } + + @Test + void shouldNotAddAnyWarnings() { + doReturn(List.of(FormcycleAttachmentTestFactory.create())).when(executor).getAttachedFiles(any()); + + var result = executor.addRepresentations(FormDataTestFactory.createBuilder().clearWarnings().build()); + + assertThat(result.getWarnings()).isEmpty(); + } + + @Test + void shouldCallBuildMissingRepresentationsWarning() { + doReturn(Collections.emptyList()).when(executor).getAttachedFiles(any()); + doReturn(warning).when(executor).buildMissingRepresentationsWarning(any()); + + executor.addRepresentations(formData); + + verify(executor).buildMissingRepresentationsWarning(formData.getRequestId()); + } + + @Test + void shouldAddWhenMissingRepresentations() { + doReturn(Collections.emptyList()).when(executor).getAttachedFiles(any()); + doReturn(warning).when(executor).buildMissingRepresentationsWarning(any()); + + var result = executor.addRepresentations(formData); + + assertThat(result.getWarnings()).hasSize(1).first().isSameAs(warning); + } + + } + + @Nested + class TestAddAttachments { + + @Mock + private Warning warning; + + @Captor + private ArgumentCaptor<Set<String>> attachmentUuidsCapture; + @Captor + private ArgumentCaptor<Predicate<String>> filterPredicateCapture; + + private FormData formData = FormDataTestFactory.createBuilder().clearAttachments().build(); + + @Test + void shouldReturnSameWhenNoAttachmentUuids() { + var expectedFormData = FormDataTestFactory.createBuilder().clearAttachmentUuids().build(); + + var result = executor.addAttachments(expectedFormData); + + assertThat(result).isSameAs(expectedFormData); + } + + @Test + void shouldCallGetAttachedFiles() { + doReturn(List.of(FormcycleAttachmentTestFactory.create())).when(executor).getAttachedFiles(any()); + + executor.addAttachments(formData); + + verify(executor).getAttachedFiles(filterPredicateCapture.capture()); + assertThat(filterPredicateCapture.getValue().test(FormDataTestFactory.ATTACHMENT_UUID)).isTrue(); + } + + @Test + void shouldSetAttachments() { + var representation = FormcycleAttachmentTestFactory.create(); + doReturn(List.of(representation)).when(executor).getAttachedFiles(any()); + + var result = executor.addAttachments(formData); + + assertThat(result.getAttachments()).hasSize(1).first().isEqualTo(representation); + } + + @Test + void shouldNotAddAnyWarnings() { + doReturn(List.of(FormcycleAttachmentTestFactory.create())).when(executor).getAttachedFiles(any()); - verify(ozgHttpClient).send(eq(formcycleFormData), any(), any()); - } + var result = executor.addAttachments(FormDataTestFactory.createBuilder().clearWarnings().build()); - @SneakyThrows - @Test - void shouldSendAttachments() { - var expectedAttachment = FormcycleAttachmentTestFactory.create(); - doReturn(Map.of( - AttachmentType.ATTACHMENT, Set.of(expectedAttachment), - AttachmentType.REPRESENTATION, Set.of(FormcycleAttachmentTestFactory.create()))).when(executor).getAttachedFiles(any()); + assertThat(result.getWarnings()).isEmpty(); + } - executor.execute(); + @Test + void shouldCallBuildMissingAttachmentsWarning() { + doReturn(Collections.emptyList()).when(executor).getAttachedFiles(any()); + doReturn(warning).when(executor).buildMissingAttachmentsWarning(any()); - verify(ozgHttpClient).send(any(), attachmentsCapture.capture(), any()); - assertThat(attachmentsCapture.getValue()).containsExactlyInAnyOrder(expectedAttachment); - } + executor.addAttachments(formData); - @SneakyThrows - @Test - void shouldSendRepresentations() { - var expectedRepresentations = FormcycleAttachmentTestFactory.create(); - doReturn(Map.of( - AttachmentType.ATTACHMENT, Set.of(FormcycleAttachmentTestFactory.create()), - AttachmentType.REPRESENTATION, Set.of(expectedRepresentations))).when(executor).getAttachedFiles(any()); + verify(executor).buildMissingAttachmentsWarning(formData.getRequestId()); + } - executor.execute(); + @Test + void shouldAddWhenMissingAttachments() { + doReturn(Collections.emptyList()).when(executor).getAttachedFiles(any()); + doReturn(warning).when(executor).buildMissingAttachmentsWarning(any()); - verify(ozgHttpClient).send(any(), any(), attachmentsCapture.capture()); - assertThat(attachmentsCapture.getValue()).containsExactlyInAnyOrder(expectedRepresentations); - } + var result = executor.addAttachments(formData); + assertThat(result.getWarnings()).hasSize(1).first().isSameAs(warning); } + } @Nested @DisplayName("Attachment's handling") - class TestGetAttachments { + class TestGetAttachedFiles { @Mock private Attachment attachment; @@ -205,44 +295,32 @@ class OzgPluginExecutorTest { void shouldReturnEmpty() { when(attachmentSupplier.get()).thenReturn(Collections.emptyList()); - var attachedFiles = getAttachedFiles(Collections.emptySet()); + var attachedFiles = executor.getAttachedFiles(uuid -> true); assertThat(attachedFiles).isEmpty(); } @Test - void shouldGetAttachments() { - var expectedAttachment = initAttachment(attachment); - - var attachedFiles = getAttachedFiles(Set.of(FormcycleAttachmentTestFactory.UUID)); - - assertThat(attachedFiles).hasSize(1).containsOnly(Map.entry(AttachmentType.ATTACHMENT, Set.of(expectedAttachment))); - } - - @Test - void shouldGetRepresentations() { - var expectedAttachment = initAttachment(representation); + void shouldCallMapper() { + initAttachment(); - var attachedFiles = getAttachedFiles(Set.of(FormcycleAttachmentTestFactory.UUID)); + executor.getAttachedFiles(uuid -> true); - assertThat(attachedFiles).hasSize(1).containsOnly(Map.entry(AttachmentType.ATTACHMENT, Set.of(expectedAttachment))); + verify(attachmentMapper).map(attachment); } @Test - @DisplayName("should return all attachments as representations when no upload fields") - @SneakyThrows - void shouldGetAllRepresentations() { - when(attachmentMapper.map(any())).thenAnswer(invocation -> mock(FormcycleAttachment.class)); - when(attachmentSupplier.get()).thenReturn(List.of(attachment, representation)); + void shouldApplyFilterAndReturnAttachments() { + var expectedAttachment = initAttachment(); + when(representation.getUUID()).thenReturn(UUID.randomUUID().toString()); + when(attachmentSupplier.get()).thenReturn(List.of(representation, attachment)); - var attachedFiles = getAttachedFiles(Collections.emptySet()); + var attachedFiles = executor.getAttachedFiles(FormcycleAttachmentTestFactory.UUID::equals); - assertThat(attachedFiles).hasSize(1); - assertThat(attachedFiles.get(AttachmentType.REPRESENTATION)).hasSize(2); + assertThat(attachedFiles).hasSize(1).containsExactly(expectedAttachment); } - @SneakyThrows - private FormcycleAttachment initAttachment(Attachment attachment) { + private FormcycleAttachment initAttachment() { var expectedAttachment = FormcycleAttachmentTestFactory.create(); when(attachmentMapper.map(any())).thenReturn(expectedAttachment); when(attachment.getUUID()).thenReturn(FormcycleAttachmentTestFactory.UUID); @@ -250,29 +328,128 @@ class OzgPluginExecutorTest { return expectedAttachment; } - @SneakyThrows - private Map<AttachmentType, Set<FormcycleAttachment>> getAttachedFiles(Set<String> ids) { - return executor.getAttachedFiles(ids); + } + + @Nested + class TestBuildMissingRepresentationsWarning { + + private final String REQUEST_ID = "REQUEST_ID"; + + @Test + void shouldSetErrorCode() { + var warning = executor.buildMissingRepresentationsWarning(REQUEST_ID); + + assertThat(warning.getErrorCode()).isEqualTo(OzgPluginSoftError.MISSING_REPRESENTATION.name()); + } + + @Test + void shouldSetMessage() { + var warning = executor.buildMissingRepresentationsWarning(REQUEST_ID); + + assertThat(warning.getMessage()).contains(REQUEST_ID); } } @Nested - class TestBuildWarning { + class TestBuildMissingAttachmentsWarning { - private final String MESSAGE = "message"; + private final String REQUEST_ID = "REQUEST_ID"; @Test void shouldSetErrorCode() { - var warning = executor.buildWarning(MESSAGE); + var warning = executor.buildMissingAttachmentsWarning(REQUEST_ID); - assertThat(warning.getErrorCode()).isEqualTo(OzgPluginSoftError.MISSING_REPRESENTATION.toString()); + assertThat(warning.getErrorCode()).isEqualTo(OzgPluginSoftError.MISSING_ATTACHMENTS.name()); } @Test void shouldSetMessage() { - var warning = executor.buildWarning(MESSAGE); + var warning = executor.buildMissingAttachmentsWarning(REQUEST_ID); + + assertThat(warning.getMessage()).contains(REQUEST_ID); + } + } + + @Nested + @DisplayName("Send data") + class TestSendData { + + @Mock + private FormCycleFormData formcycleFormData; + @Mock + private FormCycleConfirmationResponse response; + + @Captor + private ArgumentCaptor<List<FormcycleAttachment>> attachmentsCapture; + @Captor + private ArgumentCaptor<List<FormcycleAttachment>> representationsCapture; + + @Test + void shouldCallMapper() { + sendFormData(); + + verify(ozgCloudFormDataMapper).map(FORM_DATA); + } + + @Test + void shouldSendFormData() { + when(ozgCloudFormDataMapper.map(any())).thenReturn(formcycleFormData); + + sendFormData(); + + verify(ozgHttpClient).send(eq(formcycleFormData), any(), any()); + } + + @Test + void shouldSendAttachments() { + sendFormData(); + + verify(ozgHttpClient).send(any(), attachmentsCapture.capture(), any()); + assertThat(attachmentsCapture.getValue()).hasSize(1).first().extracting("uuid").isEqualTo(FormDataTestFactory.ATTACHMENT_UUID); + } + + @Test + void shouldSendRepresentations() { + sendFormData(); + + verify(ozgHttpClient).send(any(), any(), representationsCapture.capture()); + assertThat(representationsCapture.getValue()).hasSize(1).first().extracting("uuid").isEqualTo(FormDataTestFactory.REPRESENTATION_UUID); + } + + @Test + void shouldReturnResponse() { + when(ozgHttpClient.send(any(), any(), any())).thenReturn(response); + + var result = sendFormData(); + + assertThat(result).isSameAs(response); + } + + private FormCycleConfirmationResponse sendFormData() { + return executor.sendFormData(FORM_DATA); + } + } + + @Nested + class TestBuildExecutionResults { + + @Mock + private Warning warning; + + @Test + void shouldSetVorgangNummer() { + var result = executor.buildExecutionResult(FormCycleConfirmationResponseTestFactory.create(), FORM_DATA); + + assertThat(result.getVorgangnummer()).isEqualTo(FormCycleConfirmationResponseTestFactory.VORGANG_NUMMER); + } + + @Test + void shouldSetWarnings() { + var formData = FormDataTestFactory.createBuilder().clearWarnings().warning(warning).build(); + + var result = executor.buildExecutionResult(FormCycleConfirmationResponseTestFactory.create(), formData); - assertThat(warning.getMessage()).isEqualTo(MESSAGE); + assertThat(result.getWarnings()).containsExactly(warning); } } } \ No newline at end of file diff --git a/src/test/java/de/ozgcloud/formcycle/attachment/FormcycleAttachmentTestFactory.java b/src/test/java/de/ozgcloud/formcycle/attachment/FormcycleAttachmentTestFactory.java index 7dbb6461e0503ac7598d1079bc118a214ac2bfdc..3fd7153ba0fd509691145e94ceb31da1a3e4dca2 100644 --- a/src/test/java/de/ozgcloud/formcycle/attachment/FormcycleAttachmentTestFactory.java +++ b/src/test/java/de/ozgcloud/formcycle/attachment/FormcycleAttachmentTestFactory.java @@ -19,7 +19,7 @@ public class FormcycleAttachmentTestFactory { return createBuilder().build(); } - static FormcycleAttachmentBuilder createBuilder() { + public static FormcycleAttachmentBuilder createBuilder() { return FormcycleAttachment.builder() .uuid(UUID) .fileName(FILE_NAME) diff --git a/src/test/java/de/ozgcloud/formcycle/formdata/FormDataTestFactory.java b/src/test/java/de/ozgcloud/formcycle/formdata/FormDataTestFactory.java index dba1ab267371b28e71824c28aa6050a2a648cc6b..7054470000ee7b948993df84531800953f35ab65 100644 --- a/src/test/java/de/ozgcloud/formcycle/formdata/FormDataTestFactory.java +++ b/src/test/java/de/ozgcloud/formcycle/formdata/FormDataTestFactory.java @@ -24,12 +24,19 @@ package de.ozgcloud.formcycle.formdata; import java.util.List; import java.util.Set; +import java.util.UUID; + +import de.ozgcloud.formcycle.attachment.FormcycleAttachmentTestFactory; public class FormDataTestFactory { + public static final long FORM_ID = 1; + public static final String FORM_ID_STR = String.valueOf(FORM_ID); public static final String FORM_NAME = "formular"; public static final String ORGANISATIONS_EINHEIT_ID = "12345"; public static final String ATTACHMENT_ID = "file.pdf"; + public static final String ATTACHMENT_UUID = UUID.randomUUID().toString(); + public static final String REPRESENTATION_UUID = UUID.randomUUID().toString(); public static final String FIELD_VALUE_1 = "on"; public static final List<FormNode> FIELD_DATA = List.of(FormNodeTestFactory.create()); @@ -39,10 +46,14 @@ public class FormDataTestFactory { public static FormData.FormDataBuilder createBuilder() { return FormData.builder() + .formId(FORM_ID) .formName(FORM_NAME) .organisationsEinheitId(ORGANISATIONS_EINHEIT_ID) .fieldData(FIELD_DATA) .attachmentNames(Set.of(ATTACHMENT_ID)) + .attachmentUuids(Set.of(ATTACHMENT_UUID)) + .representation(FormcycleAttachmentTestFactory.createBuilder().uuid(REPRESENTATION_UUID).build()) + .attachment(FormcycleAttachmentTestFactory.createBuilder().uuid(ATTACHMENT_UUID).build()) .serviceKonto(ServiceKontoTestFactory.create()); } } diff --git a/src/test/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapperTest.java b/src/test/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapperTest.java index 82cbc184f4b32628d8aa357a2d4e9e3f0d7e43aa..b3b2eb22f14480efedd4786146e9d273379d1ac3 100644 --- a/src/test/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapperTest.java +++ b/src/test/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapperTest.java @@ -165,7 +165,7 @@ class OzgCloudFormDataMapperTest { var formFields = mapper.mapFormFields(formNode); - assertThat(formFields).first().extracting(GrpcFormField::getLabel).toString().isEmpty(); + assertThat(formFields).first().extracting(GrpcFormField::getLabel, STRING).isEmpty(); } @Test @@ -174,7 +174,7 @@ class OzgCloudFormDataMapperTest { var formFields = mapper.mapFormFields(formNode); - assertThat(formFields).first().extracting(GrpcFormField::getName).toString().isEmpty(); + assertThat(formFields).first().extracting(GrpcFormField::getName, STRING).isEmpty(); } } @@ -245,7 +245,6 @@ class OzgCloudFormDataMapperTest { @Test void shouldSetLabel() { - var subform = mapper.mapSubForm(formNode).get(); assertThat(subform.getLabel()).isEqualTo(StructureMockFactory.ITEM_TITLE); @@ -355,31 +354,45 @@ class OzgCloudFormDataMapperTest { } @Nested - @DisplayName("Map header") - class TestHeader { + @DisplayName("build header") + class TestBuildHeader { private final FormData formData = FormDataTestFactory.create(); @Test void shouldSetReceivedTime() { - var ozgFormDataHeader = mapper.map(formData).getHeader(); + var ozgFormDataHeader = mapper.buildHeader(formData); assertThat(ozgFormDataHeader.getReceivedAt()).isNotNull(); } + @Test + void shouldSetFormId() { + var ozgFormDataHeader = mapper.buildHeader(formData); + + assertThat(ozgFormDataHeader.getFormId()).isEqualTo(FORM_ID_STR); + } + @Test void shouldSetFormName() { - var ozgFormDataHeader = mapper.map(formData).getHeader(); + var ozgFormDataHeader = mapper.buildHeader(formData); assertThat(ozgFormDataHeader.getFormName()).isEqualTo(FormDataTestFactory.FORM_NAME); } @Test void shouldSetOrganisationsEinheitId() { - var ozgFormDataHeader = mapper.map(formData).getHeader(); + var ozgFormDataHeader = mapper.buildHeader(formData); assertThat(ozgFormDataHeader.getOrganisationsEinheitId()).isEqualTo(ORGANISATIONS_EINHEIT_ID); } + + @Test + void shouldSetRequestId() { + var ozgFormDataHeader = mapper.buildHeader(formData); + + assertThat(ozgFormDataHeader.getRequestId()).isEqualTo(formData.getRequestId()); + } } @Nested diff --git a/src/test/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapterTest.java b/src/test/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapterTest.java index 8343e162c9a81ff569938cb207c0e02cd4242cba..0b4535319967d1f0114e093bbd6339854d878573 100644 --- a/src/test/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapterTest.java +++ b/src/test/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapterTest.java @@ -81,6 +81,9 @@ class PluginFormDataAdapterTest { private static final String UPLOAD_FIELD_NAME = "upload"; private final String ATTACHMENT_UUID = UUID.randomUUID().toString(); + @Mock + private Projekt project; + private FormNode formNode = FormNodeTestFactory.create(); @BeforeEach @@ -92,6 +95,8 @@ class PluginFormDataAdapterTest { doReturn(Set.of(FormDataTestFactory.ATTACHMENT_ID)).when(adapter).getAttachmentNames(any()); doReturn(Set.of(ATTACHMENT_UUID)).when(adapter).getAttachmentUuids(any()); doNothing().when(adapter).addServiceKonto(any()); + when(project.getId()).thenReturn(FormDataTestFactory.FORM_ID); + when(environmentData.getProject()).thenReturn(project); } @Test @@ -108,6 +113,13 @@ class PluginFormDataAdapterTest { verify(adapter).getUploadFieldNames(); } + @Test + void shouldSetFormId() { + var result = adapter.readFormData(); + + assertThat(result.getFormId()).isEqualTo(FormDataTestFactory.FORM_ID); + } + @Test void shouldSetFormName() { var result = adapter.readFormData(); @@ -358,15 +370,6 @@ class PluginFormDataAdapterTest { @Mock private FormFieldMetaData formFieldMetaData; - private Map<String, Map<String, String>> valueOptionsMap = Map.of(PluginDataTestFactory.FIELD_VALUE, - Map.of(PluginFormDataAdapter.TEXT_KEY, PluginDataTestFactory.TEXT_MAP_VALUE)); - - @BeforeEach - void setup() { - // when(formFieldMetaData.getType()).thenReturn(EFormFieldTyp.SELECT); - // when(formDataAdapter.getFieldMetaData(anyString(), anyBoolean())).thenReturn(formFieldMetaData); - } - @DisplayName("should return input when") @ParameterizedTest(name = "value = \"{0}\"") @NullAndEmptySource