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

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

commit 5f80b1b8016a9658325f8b4a9a9e9fdcc578e3b7
Author: danhaywood <[email protected]>
AuthorDate: Thu Feb 15 00:00:49 2024 +0000

    CAUSEWAY-3676: adds test to download from URL
---
 ...est.find_department_and_add_staff_members._.gql | 70 ++++++++++++++++
 ...d_department_and_add_staff_members._.invoke.gql | 27 ------
 ..._department_and_add_staff_members.approved.json | 97 +++++++++++++++++++---
 ..._department_and_add_staff_members.choices._.gql | 22 -----
 .../queryandmutations/Department_IntegTest.java    | 22 +----
 ...d_staff_member_by_name_and_download_photo._.gql | 16 ++++
 ...member_by_name_and_download_photo.approved.json | 18 ++++
 .../e2e/queryandmutations/Staff_IntegTest.java     | 49 ++++++++++-
 .../viewer/CausewayModuleViewerGraphqlViewer.java  |  7 +-
 .../viewer/controller/BlobBytesController.java     | 50 ++++++-----
 10 files changed, 271 insertions(+), 107 deletions(-)

diff --git 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.find_department_and_add_staff_members._.gql
 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.find_department_and_add_staff_members._.gql
new file mode 100644
index 0000000000..8363554ae5
--- /dev/null
+++ 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.find_department_and_add_staff_members._.gql
@@ -0,0 +1,70 @@
+{
+  Scenario(name: "can add staff members") {
+    Given {
+      university_dept_Departments {
+        findDepartmentByName {
+          invoke(name: "Classics") {
+            staffMembers {
+              get {
+                name {
+                  get
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    When {
+      university_dept_Departments {
+        findDepartmentByName {
+          invoke(name: "Classics") {
+            addStaffMembers {
+              params {
+                staffMembers {
+                  datatype
+                  choices {
+                    _gqlv_meta {
+                      id
+                      saveAs(ref: "staff-member")
+                    }
+                    name {
+                      get
+                    }
+                  }
+                }
+              }
+              invokeIdempotent(staffMembers: [{ref: "staff-member"}, {ref: 
"staff-member-2"}]) {
+                name {
+                  get
+                }
+                staffMembers {
+                  get {
+                    name {
+                      get
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    Then {
+      university_dept_Departments {
+        findDepartmentByName {
+          invoke(name: "Classics") {
+            staffMembers {
+              get {
+                name {
+                  get
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.find_department_and_add_staff_members._.invoke.gql
 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.find_department_and_add_staff_members._.invoke.gql
deleted file mode 100644
index 1b5452b974..0000000000
--- 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.find_department_and_add_staff_members._.invoke.gql
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-  university_dept_Departments {
-    findDepartmentByName {
-      invoke(name: "Classics") {
-        addStaffMembers {
-          params {
-            staffMembers {
-              datatype
-            }
-          }
-          invokeIdempotent(staffMembers: [{id: "$staffMemberId1"}, {id: 
"$staffMemberId2"}]) {
-            name {
-              get
-            }
-            staffMembers {
-              get {
-                name {
-                  get
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-}
diff --git 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.find_department_and_add_staff_members.approved.json
 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.find_department_and_add_staff_members.approved.json
index 8126e9ff36..960446e13a 100644
--- 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.find_department_and_add_staff_members.approved.json
+++ 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.find_department_and_add_staff_members.approved.json
@@ -1,18 +1,93 @@
 {
   "data" : {
-    "university_dept_Departments" : {
-      "findDepartmentByName" : {
-        "invoke" : {
-          "addStaffMembers" : {
-            "params" : {
+    "Scenario" : {
+      "Given" : {
+        "university_dept_Departments" : {
+          "findDepartmentByName" : {
+            "invoke" : {
               "staffMembers" : {
-                "datatype" : "university_dept_StaffMember"
+                "get" : [ {
+                  "name" : {
+                    "get" : "Gerry Jones"
+                  }
+                }, {
+                  "name" : {
+                    "get" : "Letitia Leadbetter"
+                  }
+                } ]
               }
-            },
-            "invokeIdempotent" : {
-              "name" : {
-                "get" : "Classics"
-              },
+            }
+          }
+        }
+      },
+      "When" : {
+        "university_dept_Departments" : {
+          "findDepartmentByName" : {
+            "invoke" : {
+              "addStaffMembers" : {
+                "params" : {
+                  "staffMembers" : {
+                    "datatype" : "university_dept_StaffMember",
+                    "choices" : [ {
+                      "_gqlv_meta" : {
+                        "id" : "15",
+                        "saveAs" : "staff-member"
+                      },
+                      "name" : {
+                        "get" : "John Gartner"
+                      }
+                    }, {
+                      "_gqlv_meta" : {
+                        "id" : "16",
+                        "saveAs" : "staff-member"
+                      },
+                      "name" : {
+                        "get" : "Margaret Randall"
+                      }
+                    }, {
+                      "_gqlv_meta" : {
+                        "id" : "14",
+                        "saveAs" : "staff-member"
+                      },
+                      "name" : {
+                        "get" : "Mervin Hughes"
+                      }
+                    } ]
+                  }
+                },
+                "invokeIdempotent" : {
+                  "name" : {
+                    "get" : "Classics"
+                  },
+                  "staffMembers" : {
+                    "get" : [ {
+                      "name" : {
+                        "get" : "Gerry Jones"
+                      }
+                    }, {
+                      "name" : {
+                        "get" : "John Gartner"
+                      }
+                    }, {
+                      "name" : {
+                        "get" : "Letitia Leadbetter"
+                      }
+                    }, {
+                      "name" : {
+                        "get" : "Margaret Randall"
+                      }
+                    } ]
+                  }
+                }
+              }
+            }
+          }
+        }
+      },
+      "Then" : {
+        "university_dept_Departments" : {
+          "findDepartmentByName" : {
+            "invoke" : {
               "staffMembers" : {
                 "get" : [ {
                   "name" : {
diff --git 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.find_department_and_add_staff_members.choices._.gql
 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.find_department_and_add_staff_members.choices._.gql
deleted file mode 100644
index 0c429c93b9..0000000000
--- 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.find_department_and_add_staff_members.choices._.gql
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-  university_dept_Departments {
-    findDepartmentByName {
-      invoke(name: "Classics") {
-        addStaffMembers {
-          params {
-            staffMembers {
-              choices {
-                _gqlv_meta {
-                  id
-                }
-                name {
-                  get
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-}
diff --git 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.java
 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.java
index 5db64cac19..a24e276e2f 100644
--- 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.java
+++ 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Department_IntegTest.java
@@ -127,28 +127,8 @@ public class Department_IntegTest extends 
Abstract_IntegTest {
     void find_department_and_add_staff_members() throws Exception {
 
         // when, then
-        String submit = submit("choices");
-
-        ObjectMapper mapper = new ObjectMapper();
-        JsonNode root = mapper.readTree(submit);
-
-        JsonNode staffMembersNode = 
root.at("/data/university_dept_Departments/findDepartmentByName/invoke/addStaffMembers/params/staffMembers/choices");
-
-        List<String> ids = new ArrayList<>();
-        staffMembersNode.forEach(staffMemberNode -> {
-            String id = staffMemberNode.get("_gqlv_meta").get("id").asText();
-            if (!_Strings.isNullOrEmpty(id)) {
-                ids.add(id);
-            }
-        });
-
-        Assertions.assertThat(ids).hasSize(3);
-
-        val replacements = _Maps.unmodifiable(
-                "$staffMemberId1", ids.get(0),
-                "$staffMemberId2", ids.get(1));
+        Approvals.verify(submit(), jsonOptions());
 
-        Approvals.verify(submit("invoke", replacements), jsonOptions());
     }
 
     @Test
diff --git 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Staff_IntegTest.find_staff_member_by_name_and_download_photo._.gql
 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Staff_IntegTest.find_staff_member_by_name_and_download_photo._.gql
new file mode 100644
index 0000000000..51ac1345c4
--- /dev/null
+++ 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Staff_IntegTest.find_staff_member_by_name_and_download_photo._.gql
@@ -0,0 +1,16 @@
+{
+  university_dept_Staff {
+    findStaffMemberByName {
+      invoke(name: "Gerry Jones") {
+        name {
+          get
+        }
+        photo {
+          get {
+            bytes
+          }
+        }
+      }
+    }
+  }
+}
diff --git 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Staff_IntegTest.find_staff_member_by_name_and_download_photo.approved.json
 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Staff_IntegTest.find_staff_member_by_name_and_download_photo.approved.json
new file mode 100644
index 0000000000..8fe6c5418c
--- /dev/null
+++ 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Staff_IntegTest.find_staff_member_by_name_and_download_photo.approved.json
@@ -0,0 +1,18 @@
+{
+  "data" : {
+    "university_dept_Staff" : {
+      "findStaffMemberByName" : {
+        "invoke" : {
+          "name" : {
+            "get" : "Gerry Jones"
+          },
+          "photo" : {
+            "get" : {
+              "bytes" : 
"///graphql/object/university.dept.StaffMember:13/photo/blobBytes"
+            }
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Staff_IntegTest.java
 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Staff_IntegTest.java
index d0c59e25a8..503244c1aa 100644
--- 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Staff_IntegTest.java
+++ 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/queryandmutations/Staff_IntegTest.java
@@ -18,6 +18,11 @@
  */
 package org.apache.causeway.viewer.graphql.viewer.test.e2e.queryandmutations;
 
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
 import java.util.Optional;
 
 import org.apache.causeway.viewer.graphql.viewer.test.e2e.Abstract_IntegTest;
@@ -35,12 +40,13 @@ import org.springframework.test.context.ActiveProfiles;
 import org.springframework.transaction.annotation.Propagation;
 
 import org.apache.causeway.applib.services.bookmark.Bookmark;
-import org.apache.causeway.commons.internal.collections._Maps;
-import org.apache.causeway.viewer.graphql.viewer.test.domain.dept.Department;
 import org.apache.causeway.viewer.graphql.viewer.test.domain.dept.StaffMember;
 
 import lombok.val;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
 
 //NOT USING @Transactional since we are running server within same transaction 
otherwise
 @Order(60)
@@ -116,4 +122,43 @@ public class Staff_IntegTest extends Abstract_IntegTest {
         Approvals.verify(submit(), jsonOptions());
 
     }
+
+    @Test
+    @UseReporter(DiffReporter.class)
+    void find_staff_member_by_name_and_download_photo() throws Exception {
+
+        String response = submit();
+        Approvals.verify(response, jsonOptions());
+
+        ObjectMapper mapper = new ObjectMapper();
+        JsonNode root = mapper.readTree(response);
+
+        String url = root
+                
.at("/data/university_dept_Staff/findStaffMemberByName/invoke/photo/get/bytes")
+                .asText();
+
+        
assertThat(url).matches("///graphql/object/university.dept.StaffMember:(\\d+)/photo/blobBytes");
+
+        val httpResponse = submitReturningBytes(url);
+
+        assertThat(httpResponse.statusCode()).isEqualTo(200);
+        byte[] bytes = httpResponse.body();
+        assertThat(bytes).isNotEmpty();
+
+    }
+
+    private HttpResponse<byte[]> submitReturningBytes(String url) throws 
IOException, InterruptedException {
+
+        val urlSuffix = url.substring(3); // strip off the '///' prefix
+        val uri = URI.create(String.format("http://0.0.0.0:%d/%s";, port, 
urlSuffix));
+
+        HttpRequest httpRequest = HttpRequest.newBuilder().
+                uri(uri).
+                GET().
+                build();
+
+        HttpClient httpClient = HttpClient.newHttpClient();
+        return httpClient.send(httpRequest, 
HttpResponse.BodyHandlers.ofByteArray());
+    }
+
 }
diff --git 
a/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/CausewayModuleViewerGraphqlViewer.java
 
b/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/CausewayModuleViewerGraphqlViewer.java
index ae85d6e6da..1c28790e91 100644
--- 
a/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/CausewayModuleViewerGraphqlViewer.java
+++ 
b/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/CausewayModuleViewerGraphqlViewer.java
@@ -18,6 +18,8 @@
  */
 package org.apache.causeway.viewer.graphql.viewer;
 
+import 
org.apache.causeway.viewer.graphql.viewer.controller.BlobBytesController;
+
 import 
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration;
 import org.springframework.boot.autoconfigure.graphql.GraphQlCorsProperties;
@@ -42,7 +44,10 @@ import 
org.apache.causeway.viewer.graphql.model.CausewayModuleViewerGraphqlModel
 
         // autoconfigurations
         GraphQlAutoConfiguration.class,
-        GraphQlWebMvcAutoConfiguration.class
+        GraphQlWebMvcAutoConfiguration.class,
+
+        // controllers
+        BlobBytesController.class
 })
 @EnableConfigurationProperties({
         GraphQlProperties.class, GraphQlCorsProperties.class
diff --git 
a/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/controller/BlobBytesController.java
 
b/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/controller/BlobBytesController.java
index fc5ae3e523..a72670ce79 100644
--- 
a/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/controller/BlobBytesController.java
+++ 
b/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/controller/BlobBytesController.java
@@ -10,6 +10,7 @@ import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import org.apache.causeway.applib.services.bookmark.Bookmark;
@@ -23,13 +24,37 @@ import lombok.Value;
 
 import java.util.Optional;
 
-@RestController(value = "/graphql/object")
+@RestController()
+@RequestMapping("/graphql/object")
 @RequiredArgsConstructor(onConstructor_ = {@Inject})
 public class BlobBytesController {
 
     private final BookmarkService bookmarkService;
     private final ObjectManager objectManager;
 
+    @GetMapping(value = "/{logicalTypeName}:{id}/{propertyId}/blobBytes")
+    public ResponseEntity<byte[]> propertyBlobBytes(
+            @PathVariable final String logicalTypeName,
+            @PathVariable final String id,
+            @PathVariable final String propertyId) {
+
+        return 
bookmarkService.lookup(Bookmark.forLogicalTypeNameAndIdentifier(logicalTypeName,
 id))
+                .map(objectManager::adapt)
+                .map(managedObject -> 
ManagedObjectAndPropertyIfAny.of(managedObject, 
managedObject.getSpecification().getProperty(propertyId)))
+                .filter(ManagedObjectAndPropertyIfAny::isPropertyPresent)
+                .map(ManagedObjectAndProperty::of)
+                .map(ManagedObjectAndProperty::value)
+                .map(ManagedObject::getPojo)
+                .filter(Blob.class::isInstance)
+                .map(Blob.class::cast)
+                .map(blob -> ResponseEntity.ok()
+                        .contentType(MediaType.APPLICATION_PDF)
+                        .header(HttpHeaders.CONTENT_DISPOSITION, 
ContentDisposition.attachment().filename(blob.getName()).build().toString())
+                        .contentLength(blob.getBytes().length)
+                        .body(blob.getBytes()))
+                .orElse(ResponseEntity.notFound().build());
+    }
+
     @Value(staticConstructor = "of")
     private static class ManagedObjectAndPropertyIfAny {
         ManagedObject owningObject;
@@ -50,31 +75,10 @@ public class BlobBytesController {
         ManagedObject owningObject;
         OneToOneAssociation property;
 
-        public ManagedObject value() {
+        ManagedObject value() {
             return property.get(owningObject);
         }
     }
 
-    @GetMapping(value = "/{logicalTypeName}:{id}/{propertyId}/blobBytes")
-    public ResponseEntity<byte[]> propertyBlobBytes(
-            @PathVariable final String logicalTypeName,
-            @PathVariable final String id,
-            @PathVariable final String propertyId) {
 
-        return 
bookmarkService.lookup(Bookmark.forLogicalTypeNameAndIdentifier(logicalTypeName,
 id))
-                .map(objectManager::adapt)
-                .map(managedObject -> 
ManagedObjectAndPropertyIfAny.of(managedObject, 
managedObject.getSpecification().getProperty(propertyId)))
-                .filter(ManagedObjectAndPropertyIfAny::isPropertyPresent)
-                .map(ManagedObjectAndProperty::of)
-                .map(ManagedObjectAndProperty::value)
-                .map(ManagedObject::getPojo)
-                .filter(Blob.class::isInstance)
-                .map(Blob.class::cast)
-                .map(blob -> ResponseEntity.ok()
-                        .contentType(MediaType.APPLICATION_PDF)
-                        .header(HttpHeaders.CONTENT_DISPOSITION, 
ContentDisposition.attachment().filename(blob.getName()).build().toString())
-                        .contentLength(blob.getBytes().length)
-                        .body(blob.getBytes()))
-                .orElse(ResponseEntity.notFound().build());
-    }
 }

Reply via email to