fix: merge pdf pipeline validation (#5799)

Co-authored-by: RenzoMXD <[email protected]>
This commit is contained in:
Renzo
2026-03-06 00:14:30 +00:00
committed by GitHub
co-authored by RenzoMXD
parent 30b0924d6b
commit c77242d943
3 changed files with 101 additions and 3 deletions
@@ -25,8 +25,9 @@ public class ApiEndpoint {
} }
public boolean areParametersValid(Map<String, Object> providedParams) { public boolean areParametersValid(Map<String, Object> providedParams) {
for (String requiredParam : parameters.keySet()) { for (Map.Entry<String, JsonNode> entry : parameters.entrySet()) {
if (!providedParams.containsKey(requiredParam)) { boolean isRequired = entry.getValue().path("required").asBoolean(false);
if (isRequired && !providedParams.containsKey(entry.getKey())) {
return false; return false;
} }
} }
@@ -18,6 +18,11 @@ class ApiEndpointTest {
private final ObjectMapper mapper = JsonMapper.builder().build(); private final ObjectMapper mapper = JsonMapper.builder().build();
private JsonNode postNodeWithParams(String description, String... names) { private JsonNode postNodeWithParams(String description, String... names) {
return postNodeWithParams(description, true, names);
}
private JsonNode postNodeWithParams(
String description, boolean required, String... names) {
ObjectNode post = mapper.createObjectNode(); ObjectNode post = mapper.createObjectNode();
post.put("description", description); post.put("description", description);
ArrayNode params = mapper.createArrayNode(); ArrayNode params = mapper.createArrayNode();
@@ -26,6 +31,7 @@ class ApiEndpointTest {
if (n != null) { if (n != null) {
p.put("name", n); p.put("name", n);
} }
p.put("required", required);
params.add(p); params.add(p);
} }
post.set("parameters", params); post.set("parameters", params);
@@ -92,6 +98,75 @@ class ApiEndpointTest {
assertTrue(endpoint.areParametersValid(Map.of("", 42))); assertTrue(endpoint.areParametersValid(Map.of("", 42)));
} }
@Test
void optional_parameters_can_be_omitted() {
JsonNode post = postNodeWithParams("desc", false, "fileOrder");
ApiEndpoint endpoint = new ApiEndpoint("merge", post);
assertTrue(
endpoint.areParametersValid(Map.of()),
"Should be valid when optional param is omitted");
}
@Test
void mixed_required_and_optional_validates_only_required() {
ObjectNode post = mapper.createObjectNode();
post.put("description", "merge pdfs");
ArrayNode params = mapper.createArrayNode();
ObjectNode required = mapper.createObjectNode();
required.put("name", "sortType");
required.put("required", true);
params.add(required);
ObjectNode optional = mapper.createObjectNode();
optional.put("name", "fileOrder");
optional.put("required", false);
params.add(optional);
post.set("parameters", params);
ApiEndpoint endpoint = new ApiEndpoint("/api/v1/general/merge-pdfs", post);
Map<String, Object> provided = new HashMap<>();
provided.put("sortType", "byFileName");
assertTrue(
endpoint.areParametersValid(provided),
"Should pass when required params present and optional omitted");
provided.put("fileOrder", "0,1,2");
assertTrue(
endpoint.areParametersValid(provided),
"Should also pass when optional param is provided");
}
@Test
void missing_required_param_with_optional_present_still_fails() {
ObjectNode post = mapper.createObjectNode();
post.put("description", "desc");
ArrayNode params = mapper.createArrayNode();
ObjectNode required = mapper.createObjectNode();
required.put("name", "file");
required.put("required", true);
params.add(required);
ObjectNode optional = mapper.createObjectNode();
optional.put("name", "fileOrder");
optional.put("required", false);
params.add(optional);
post.set("parameters", params);
ApiEndpoint endpoint = new ApiEndpoint("x", post);
Map<String, Object> provided = new HashMap<>();
provided.put("fileOrder", "0,1");
assertFalse(
endpoint.areParametersValid(provided),
"Should fail when required param is missing even if optional is present");
}
@Test @Test
void toString_contains_name_and_parameter_names() { void toString_contains_name_and_parameter_names() {
JsonNode post = postNodeWithParams("desc", "file", "mode"); JsonNode post = postNodeWithParams("desc", "file", "mode");
@@ -74,15 +74,37 @@ class ApiDocServiceTest {
@Test @Test
void isValidOperationChecksRequiredParameters() throws Exception { void isValidOperationChecksRequiredParameters() throws Exception {
String json = String json =
"{\"description\": \"desc\", \"parameters\": [{\"name\":\"param1\"}, {\"name\":\"param2\"}]}"; "{\"description\": \"desc\", \"parameters\": [{\"name\":\"param1\", \"required\": true}, {\"name\":\"param2\", \"required\": true}]}";
JsonNode postNode = mapper.readTree(json); JsonNode postNode = mapper.readTree(json);
ApiEndpoint endpoint = new ApiEndpoint("/op", postNode); ApiEndpoint endpoint = new ApiEndpoint("/op", postNode);
setApiDocumentation(Map.of("/op", endpoint)); setApiDocumentation(Map.of("/op", endpoint));
setApiDocsJsonRootNode(); setApiDocsJsonRootNode();
// All required params provided - valid
assertTrue(apiDocService.isValidOperation("/op", Map.of("param1", "a", "param2", "b"))); assertTrue(apiDocService.isValidOperation("/op", Map.of("param1", "a", "param2", "b")));
// Missing required param2 - invalid
assertFalse(apiDocService.isValidOperation("/op", Map.of("param1", "a"))); assertFalse(apiDocService.isValidOperation("/op", Map.of("param1", "a")));
// Missing required param1 - invalid
assertFalse(apiDocService.isValidOperation("/op", Map.of("param2", "b")));
}
@Test
void isValidOperationAllowsOptionalParameters() throws Exception {
String json =
"{\"description\": \"desc\", \"parameters\": [{\"name\":\"param1\", \"required\": false}, {\"name\":\"param2\", \"required\": false}]}";
JsonNode postNode = mapper.readTree(json);
ApiEndpoint endpoint = new ApiEndpoint("/op", postNode);
setApiDocumentation(Map.of("/op", endpoint));
setApiDocsJsonRootNode();
// All optional params provided - valid
assertTrue(apiDocService.isValidOperation("/op", Map.of("param1", "a", "param2", "b")));
// Only one optional param provided - valid
assertTrue(apiDocService.isValidOperation("/op", Map.of("param1", "a")));
// No optional params provided - valid
assertTrue(apiDocService.isValidOperation("/op", Map.of()));
} }
@Test @Test