This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch CAUSEWAY-3718
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit fe1404fa2b7d24a8c50ebec73b85e62ca0a9abb3
Author: danhaywood <[email protected]>
AuthorDate: Fri Apr 5 09:53:03 2024 +0100

    CAUSEWAY-3718: adds failing integ test to demonstrate the issue
---
 viewers/restfulobjects/test/pom.xml                |   6 +
 .../restfulobjects/test/domain/dom/Staff.java      |  12 ++
 .../test/scenarios/staff/Staff_IntegTest.java      | 163 +++++++++++++++++++++
 3 files changed, 181 insertions(+)

diff --git a/viewers/restfulobjects/test/pom.xml 
b/viewers/restfulobjects/test/pom.xml
index bd9d4d2400..9ba9f05a37 100644
--- a/viewers/restfulobjects/test/pom.xml
+++ b/viewers/restfulobjects/test/pom.xml
@@ -173,5 +173,11 @@
             <scope>test</scope>
         </dependency>
 
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
 </project>
diff --git 
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/domain/dom/Staff.java
 
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/domain/dom/Staff.java
index 11923234d1..23e83f6a6d 100644
--- 
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/domain/dom/Staff.java
+++ 
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/domain/dom/Staff.java
@@ -27,6 +27,7 @@ import org.apache.causeway.applib.annotation.Action;
 import org.apache.causeway.applib.annotation.DomainService;
 import org.apache.causeway.applib.annotation.PriorityPrecedence;
 import org.apache.causeway.applib.annotation.SemanticsOf;
+import org.apache.causeway.applib.value.Blob;
 
 import lombok.RequiredArgsConstructor;
 
@@ -46,6 +47,17 @@ public class Staff {
         return staffMemberRepository.create(name, department);
     }
 
+    @Action(semantics = SemanticsOf.NON_IDEMPOTENT)
+    public StaffMember createStaffMemberWithPhoto(
+            final String name,
+            final Department department,
+            final Blob photo
+    ){
+        final var staffMember = createStaffMember(name, department);
+        staffMember.setPhoto(photo);
+        return staffMember;
+    }
+
     @Action(semantics = SemanticsOf.SAFE)
     public List<StaffMember> findAllStaffMembers(){
         return staffMemberRepository.findAll();
diff --git 
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.java
 
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.java
new file mode 100644
index 0000000000..2c3dcc72c3
--- /dev/null
+++ 
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.java
@@ -0,0 +1,163 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.causeway.viewer.restfulobjects.test.scenarios.staff;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.core.Response;
+
+import org.apache.causeway.applib.services.bookmark.Bookmark;
+import 
org.apache.causeway.core.metamodel.facets.param.choices.ActionParameterChoicesFacetFromAction;
+
+import org.apache.causeway.viewer.restfulobjects.test.domain.dom.Department;
+
+import org.approvaltests.Approvals;
+import org.approvaltests.reporters.DiffReporter;
+import org.approvaltests.reporters.UseReporter;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import 
org.apache.causeway.viewer.restfulobjects.test.scenarios.Abstract_IntegTest;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.converter.json.GsonBuilderUtils;
+import org.springframework.transaction.annotation.Propagation;
+
+import lombok.Getter;
+import lombok.SneakyThrows;
+import lombok.val;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Base64;
+import java.util.Optional;
+
+import com.google.common.io.Resources;
+import com.google.gson.GsonBuilder;
+
+public class Staff_IntegTest extends Abstract_IntegTest {
+
+    private GsonBuilder gsonBuilder;
+
+    @BeforeEach
+    void setup() {
+        gsonBuilder = new GsonBuilder();
+    }
+
+    @SneakyThrows
+    @Test
+    @UseReporter(DiffReporter.class)
+    public void can_create_staff_member() {
+
+        // given
+        final var staffName = "Fred Smith";
+
+        final var bookmarkBeforeIfAny = 
transactionService.callTransactional(Propagation.REQUIRED, () -> {
+            final var staffMember = 
staffMemberRepository.findByName(staffName);
+            return bookmarkService.bookmarkFor(staffMember);
+        }).valueAsNonNullElseFail();
+
+        assertThat(bookmarkBeforeIfAny).isEmpty();
+
+        final var photoEncoded = 
readFileAndEncodeAsBlob("StaffMember-photo-Bar.pdf");
+        final var requestBuilder = 
restfulClient.request("services/university.dept.Staff/actions/createStaffMemberWithPhoto/invoke");
+
+        final var body = new Body(staffName, "Classics", photoEncoded);
+        final var bodyJson = gsonBuilder.create().toJson(body);
+
+        // when
+        val response = requestBuilder.post(Entity.entity(bodyJson, 
"application/json"));
+
+        // then
+        
assertThat(response.getStatusInfo().getFamily()).isEqualTo(Response.Status.Family.SUCCESSFUL);
+        
assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
+
+        // and also json response
+        val entity = response.readEntity(String.class);
+        assertThat(response)
+                .extracting(Response::getStatus)
+                .isEqualTo(Response.Status.OK.getStatusCode());
+        Approvals.verify(entity, jsonOptions());
+
+        // and also object is created in database
+        final var bookmarkAfterIfAny = 
transactionService.callTransactional(Propagation.REQUIRED, () -> {
+            final var staffMember = 
staffMemberRepository.findByName(staffName);
+            return bookmarkService.bookmarkFor(staffMember);
+        }).valueAsNonNullElseFail();
+        assertThat(bookmarkAfterIfAny).isNotEmpty();
+    }
+
+    private String readFileAndEncodeAsBlob(String fileName) throws 
IOException, URISyntaxException {
+        byte[] bytes = 
Resources.toByteArray(Resources.getResource(Abstract_IntegTest.class, 
fileName));
+        String photoEncoded = encodePdf(fileName, bytes);
+        return photoEncoded;
+    }
+
+    private String encodePdf(final String fileName, final byte[] pdfBytes) 
throws URISyntaxException {
+        final String pdfBytesEncoded = 
Base64.getEncoder().encodeToString(pdfBytes);
+        final String encodedBlob = String.format("%s:%s:%s", fileName, 
"application/pdf", pdfBytesEncoded);
+        return encodedBlob;
+    }
+
+}
+
+
+@Getter
+class Body {
+
+    /**
+     * @param nameValue
+     * @param departmentValue
+     * @param blobValue - is the Blob encoded format: 
"filename.pdf:application/pdf:pdfBytesBase64Encoded"
+     */
+    Body(String nameValue, String departmentValue, String blobValue) {
+        photo = new Blob();
+        photo.value = blobValue;
+        name = new Name();
+        name.value = nameValue;
+        department = new Department();
+        department.value = departmentValue;
+    }
+
+    private Name name;
+
+    private Department department;
+
+    private Blob photo;
+
+    @Getter
+    static class Name {
+        private String value;
+    }
+
+    @Getter
+    static class Department {
+        private String value;
+    }
+
+    @Getter
+    static class Blob {
+        private String value;
+    }
+
+}
+

Reply via email to