From f758232393b1e7aca5550e9dff9d9ed60f281a59 Mon Sep 17 00:00:00 2001 From: Matheus Cruz Date: Wed, 26 Nov 2025 00:26:03 -0300 Subject: [PATCH 1/2] Add tests for redirect Signed-off-by: Matheus Cruz --- .../http/AbstractHttpExecutorBuilder.java | 3 - .../http/AbstractRequestSupplier.java | 32 +++- .../impl/test/HTTPWorkflowDefinitionTest.java | 177 +++++++++++++++++- .../workflows-samples/call-http-delete.yaml | 12 ++ ...ttp.yaml => call-http-find-by-status.yaml} | 2 +- .../{callGetHttp.yaml => call-http-get.yaml} | 2 +- .../workflows-samples/call-http-head.yaml | 12 ++ .../workflows-samples/call-http-options.yaml | 12 ++ ...tpAsExpr.yaml => call-http-post-expr.yaml} | 7 +- ...{callPostHttp.yaml => call-http-post.yaml} | 4 +- .../workflows-samples/call-http-put.yaml | 19 ++ .../call-http-redirect-false.yaml | 16 ++ .../call-with-response-output-expr.yaml | 18 ++ .../openapi/project-post-positive.yaml | 3 +- .../try-catch-retry-inline.yaml | 1 + .../try-catch-retry-reusable.yaml | 1 + 16 files changed, 297 insertions(+), 24 deletions(-) create mode 100644 impl/test/src/test/resources/workflows-samples/call-http-delete.yaml rename impl/test/src/test/resources/workflows-samples/{callFindByStatusHttp.yaml => call-http-find-by-status.yaml} (93%) rename impl/test/src/test/resources/workflows-samples/{callGetHttp.yaml => call-http-get.yaml} (93%) create mode 100644 impl/test/src/test/resources/workflows-samples/call-http-head.yaml create mode 100644 impl/test/src/test/resources/workflows-samples/call-http-options.yaml rename impl/test/src/test/resources/workflows-samples/{callPostHttpAsExpr.yaml => call-http-post-expr.yaml} (63%) rename impl/test/src/test/resources/workflows-samples/{callPostHttp.yaml => call-http-post.yaml} (84%) create mode 100644 impl/test/src/test/resources/workflows-samples/call-http-put.yaml create mode 100644 impl/test/src/test/resources/workflows-samples/call-http-redirect-false.yaml create mode 100644 impl/test/src/test/resources/workflows-samples/call-with-response-output-expr.yaml diff --git a/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/AbstractHttpExecutorBuilder.java b/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/AbstractHttpExecutorBuilder.java index 18eb64a29..89e76e977 100644 --- a/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/AbstractHttpExecutorBuilder.java +++ b/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/AbstractHttpExecutorBuilder.java @@ -46,9 +46,6 @@ protected static RequestSupplier buildRequestSupplier( return new WithoutBodyRequestSupplier(Invocation.Builder::head, application, redirect); case HttpMethod.OPTIONS: return new WithoutBodyRequestSupplier(Invocation.Builder::options, application, redirect); - case HttpMethod.PATCH: - return new WithBodyRequestSupplier( - (request, entity) -> request.method("patch", entity), application, body, redirect); case HttpMethod.GET: default: return new WithoutBodyRequestSupplier(Invocation.Builder::get, application, redirect); diff --git a/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/AbstractRequestSupplier.java b/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/AbstractRequestSupplier.java index 12a6c5a9d..d80b646e1 100644 --- a/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/AbstractRequestSupplier.java +++ b/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/AbstractRequestSupplier.java @@ -15,6 +15,9 @@ */ package io.serverlessworkflow.impl.executors.http; +import static jakarta.ws.rs.core.Response.Status.Family.REDIRECTION; +import static jakarta.ws.rs.core.Response.Status.Family.SUCCESSFUL; + import io.serverlessworkflow.impl.TaskContext; import io.serverlessworkflow.impl.WorkflowContext; import io.serverlessworkflow.impl.WorkflowError; @@ -36,8 +39,14 @@ public AbstractRequestSupplier(boolean redirect) { public WorkflowModel apply( Builder request, WorkflowContext workflow, TaskContext task, WorkflowModel model) { HttpModelConverter converter = HttpConverterResolver.converter(workflow, task); + + if (!redirect) { + // disable automatic redirects handling from Jersey client + request.property("jersey.config.client.followRedirects", false); + } + Response response = invokeRequest(request, converter, workflow, task, model); - validateStatus(task, response, converter); + validateStatus(task, response); return workflow .definition() .application() @@ -45,11 +54,24 @@ public WorkflowModel apply( .fromAny(response.readEntity(converter.responseType())); } - private void validateStatus(TaskContext task, Response response, HttpModelConverter converter) { - if (response.getStatusInfo().getFamily() != Family.SUCCESSFUL) { + private void validateStatus(TaskContext task, Response response) { + Family statusFamily = response.getStatusInfo().getFamily(); + boolean isSuccess = statusFamily.equals(SUCCESSFUL); + boolean isRedirect = statusFamily.equals(REDIRECTION); + boolean valid = redirect ? (isSuccess || isRedirect) : isSuccess; + + if (!valid) { + String expectedRange = redirect ? "200-399" : "200-299"; throw new WorkflowException( - converter - .errorFromResponse(WorkflowError.communication(response.getStatus(), task), response) + WorkflowError.communication( + response.getStatus(), + task, + String.format( + "The property 'redirect' is set to %s but received status %d (%s); expected status in the %s range", + redirect, + response.getStatus(), + response.getStatusInfo().getReasonPhrase(), + expectedRange)) .build()); } } diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/HTTPWorkflowDefinitionTest.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/HTTPWorkflowDefinitionTest.java index 360f691c1..78b9431be 100644 --- a/impl/test/src/test/java/io/serverlessworkflow/impl/test/HTTPWorkflowDefinitionTest.java +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/HTTPWorkflowDefinitionTest.java @@ -18,15 +18,23 @@ import static io.serverlessworkflow.api.WorkflowReader.readWorkflowFromClasspath; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowableOfType; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import io.serverlessworkflow.impl.WorkflowApplication; import io.serverlessworkflow.impl.WorkflowModel; import java.io.IOException; import java.util.Map; +import java.util.concurrent.CompletionException; import java.util.stream.Stream; +import mockwebserver3.MockResponse; +import mockwebserver3.MockWebServer; +import okhttp3.Headers; import org.assertj.core.api.Condition; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -36,6 +44,8 @@ public class HTTPWorkflowDefinitionTest { private static WorkflowApplication appl; + private static MockWebServer mockServer; + @BeforeAll static void init() { appl = WorkflowApplication.builder().build(); @@ -46,10 +56,23 @@ static void cleanup() { appl.close(); } + @BeforeEach + void setup() throws IOException { + mockServer = new MockWebServer(); + mockServer.start(9876); + } + + @AfterEach + void shutdownServer() { + mockServer.close(); + } + @ParameterizedTest @MethodSource("provideParameters") - void testWorkflowExecution(String fileName, Object input, Condition condition) + void testWorkflowExecution( + String fileName, Object input, Runnable setup, Condition condition) throws IOException { + setup.run(); assertThat( appl.workflowDefinition(readWorkflowFromClasspath(fileName)) .instance(input) @@ -94,27 +117,165 @@ private static Stream provideParameters() { Condition postCondition = new Condition( o -> o.asText().orElseThrow().equals("Javierito"), "CallHttpPostCondition"); + + Condition putCondition = + new Condition<>(o -> o.asText().get().contains("John"), "CallHttpPutCondition"); + + Condition patchCondition = + new Condition<>(o -> o.asText().get().contains("John"), "CallHttpPatchCondition"); + Map postMap = Map.of("name", "Javierito", "surname", "Unknown"); + Map putMap = Map.of("firstName", "John"); + + Runnable setupPost = + () -> + mockServer.enqueue( + new MockResponse( + 200, + Headers.of("Content-Type", "application/json"), + """ + { + "firstName": "Javierito" + } + """)); + return Stream.of( - Arguments.of("workflows-samples/callGetHttp.yaml", petInput, petCondition), + Arguments.of("workflows-samples/call-http-get.yaml", petInput, doNothing, petCondition), Arguments.of( - "workflows-samples/callGetHttp.yaml", + "workflows-samples/call-http-get.yaml", Map.of("petId", "-1"), + doNothing, new Condition( o -> o.asMap().orElseThrow().containsKey("petId"), "notFoundCondition")), Arguments.of( - "workflows-samples/call-http-endpoint-interpolation.yaml", petInput, petCondition), + "workflows-samples/call-http-endpoint-interpolation.yaml", + petInput, + doNothing, + petCondition), Arguments.of( - "workflows-samples/call-http-query-parameters.yaml", starTrekInput, starTrekCondition), + "workflows-samples/call-http-query-parameters.yaml", + starTrekInput, + doNothing, + starTrekCondition), Arguments.of( - "workflows-samples/callFindByStatusHttp.yaml", + "workflows-samples/call-http-find-by-status.yaml", Map.of(), + doNothing, new Condition(o -> !o.asCollection().isEmpty(), "HasElementCondition")), Arguments.of( "workflows-samples/call-http-query-parameters-external-schema.yaml", starTrekInput, + doNothing, starTrekCondition), - Arguments.of("workflows-samples/callPostHttp.yaml", postMap, postCondition), - Arguments.of("workflows-samples/callPostHttpAsExpr.yaml", postMap, postCondition)); + Arguments.of("workflows-samples/call-http-post.yaml", postMap, setupPost, postCondition), + Arguments.of( + "workflows-samples/call-http-delete.yaml", + Map.of(), + doNothing, + new Condition(o -> o.asMap().isEmpty(), "HTTP delete")), + Arguments.of("workflows-samples/call-http-put.yaml", putMap, doNothing, putCondition)); } + + private static final Runnable doNothing = () -> {}; + + @Test + void post_should_run_call_http_with_expression_body() { + mockServer.enqueue( + new MockResponse( + 200, + Headers.of("Content-Type", "application/json"), + """ + { + "firstName": "Javierito" + } + """)); + + assertDoesNotThrow( + () -> { + appl.workflowDefinition( + readWorkflowFromClasspath("workflows-samples/call-http-post-expr.yaml")) + .instance(Map.of("name", "Javierito", "surname", "Unknown")) + .start() + .join(); + }); + } + + @Test + void testHeadCall() { + mockServer.enqueue( + new MockResponse( + 200, + Headers.of( + Map.of( + "Content-Length", + "123", + "Content-Type", + "application/json", + "X-Custom-Header", + "CustomValue")), + "")); + assertDoesNotThrow( + () -> { + appl.workflowDefinition( + readWorkflowFromClasspath("workflows-samples/call-http-head.yaml")) + .instance(Map.of()) + .start() + .join(); + }); + } + + @Test + void testOptionsCall() { + mockServer.enqueue(new MockResponse(200, Headers.of("Allow", "GET, POST, OPTIONS"), "")); + + assertDoesNotThrow( + () -> { + appl.workflowDefinition( + readWorkflowFromClasspath("workflows-samples/call-http-options.yaml")) + .instance(Map.of()) + .start() + .join(); + }); + } + + @Test + void testRedirectAsFalse() { + mockServer.enqueue( + new MockResponse(301, Headers.of("Location", "http://localhost:9876/redirected"), "")); + + CompletionException exception = + catchThrowableOfType( + CompletionException.class, + () -> + appl.workflowDefinition( + readWorkflowFromClasspath( + "workflows-samples/call-http-redirect-false.yaml")) + .instance(Map.of()) + .start() + .join()); + + assertThat(exception.getCause().getMessage()) + .contains( + "The property 'redirect' is set to false but received status 301 (Redirection); expected status in the 200-299 range"); + } + + // @Test + // void testRedirectAsTrueWhenReceivingRedirection() { + // mockServer.enqueue( + // new MockResponse(301, Headers.of("Location", "http://localhost:9876/redirected"), "")); + // + // mockServer.enqueue( + // new MockResponse( + // 200, Headers.of("Content-Type", "application/json"), "{\"status\":\"OK\"}")); + // + // assertDoesNotThrow( + // () -> { + // appl.workflowDefinition( + // + // readWorkflowFromClasspath("workflows-samples/call-with-response-output-expr.yaml")) + // .instance(Map.of()) + // .start() + // .join(); + // }); + // } } diff --git a/impl/test/src/test/resources/workflows-samples/call-http-delete.yaml b/impl/test/src/test/resources/workflows-samples/call-http-delete.yaml new file mode 100644 index 000000000..fe36413a2 --- /dev/null +++ b/impl/test/src/test/resources/workflows-samples/call-http-delete.yaml @@ -0,0 +1,12 @@ +document: + dsl: 1.0.0-alpha1 + namespace: test + name: call-http-delete + version: 1.0.0 +do: + - deleteAuthor: + call: http + with: + method: delete + endpoint: + uri: https://fakerestapi.azurewebsites.net/api/v1/Authors/1 diff --git a/impl/test/src/test/resources/workflows-samples/callFindByStatusHttp.yaml b/impl/test/src/test/resources/workflows-samples/call-http-find-by-status.yaml similarity index 93% rename from impl/test/src/test/resources/workflows-samples/callFindByStatusHttp.yaml rename to impl/test/src/test/resources/workflows-samples/call-http-find-by-status.yaml index 6adeed8c7..5f1928e16 100644 --- a/impl/test/src/test/resources/workflows-samples/callFindByStatusHttp.yaml +++ b/impl/test/src/test/resources/workflows-samples/call-http-find-by-status.yaml @@ -1,7 +1,7 @@ document: dsl: 1.0.0-alpha1 namespace: test - name: http-call-find-by-status + name: call-http-find-by-status version: 1.0.0 do: - tryGetPet: diff --git a/impl/test/src/test/resources/workflows-samples/callGetHttp.yaml b/impl/test/src/test/resources/workflows-samples/call-http-get.yaml similarity index 93% rename from impl/test/src/test/resources/workflows-samples/callGetHttp.yaml rename to impl/test/src/test/resources/workflows-samples/call-http-get.yaml index 192b0bcdc..54573d036 100644 --- a/impl/test/src/test/resources/workflows-samples/callGetHttp.yaml +++ b/impl/test/src/test/resources/workflows-samples/call-http-get.yaml @@ -1,7 +1,7 @@ document: dsl: 1.0.0-alpha1 namespace: test - name: http-call-with-response + name: call-http-with-response version: 1.0.0 do: - tryGetPet: diff --git a/impl/test/src/test/resources/workflows-samples/call-http-head.yaml b/impl/test/src/test/resources/workflows-samples/call-http-head.yaml new file mode 100644 index 000000000..df75c8a88 --- /dev/null +++ b/impl/test/src/test/resources/workflows-samples/call-http-head.yaml @@ -0,0 +1,12 @@ +document: + dsl: 1.0.0-alpha1 + namespace: test + name: call-http-head + version: 1.0.0 +do: + - useHead: + call: http + with: + method: head + endpoint: + uri: http://localhost:9876/users/1 \ No newline at end of file diff --git a/impl/test/src/test/resources/workflows-samples/call-http-options.yaml b/impl/test/src/test/resources/workflows-samples/call-http-options.yaml new file mode 100644 index 000000000..e209f0d50 --- /dev/null +++ b/impl/test/src/test/resources/workflows-samples/call-http-options.yaml @@ -0,0 +1,12 @@ +document: + dsl: 1.0.0-alpha1 + namespace: test + name: call-http-options + version: 1.0.0 +do: + - useOptions: + call: http + with: + method: options + endpoint: + uri: http://localhost:9876/users/1 \ No newline at end of file diff --git a/impl/test/src/test/resources/workflows-samples/callPostHttpAsExpr.yaml b/impl/test/src/test/resources/workflows-samples/call-http-post-expr.yaml similarity index 63% rename from impl/test/src/test/resources/workflows-samples/callPostHttpAsExpr.yaml rename to impl/test/src/test/resources/workflows-samples/call-http-post-expr.yaml index 69b7faac3..cb6830597 100644 --- a/impl/test/src/test/resources/workflows-samples/callPostHttpAsExpr.yaml +++ b/impl/test/src/test/resources/workflows-samples/call-http-post-expr.yaml @@ -1,15 +1,16 @@ document: dsl: 1.0.0-alpha1 namespace: test - name: http-call-with-response-output-expr + name: cal-http-with-body-and-response-with-expr version: 1.0.0 do: - - postPet: + - postUsers: call: http with: + redirect: false method: post endpoint: - uri: https://fakerestapi.azurewebsites.net/api/v1/Authors + uri: http://localhost:9876/users body: "${{firstName: .name, lastName:.surname}}" output: as: .firstName \ No newline at end of file diff --git a/impl/test/src/test/resources/workflows-samples/callPostHttp.yaml b/impl/test/src/test/resources/workflows-samples/call-http-post.yaml similarity index 84% rename from impl/test/src/test/resources/workflows-samples/callPostHttp.yaml rename to impl/test/src/test/resources/workflows-samples/call-http-post.yaml index f12fec423..0f1de3290 100644 --- a/impl/test/src/test/resources/workflows-samples/callPostHttp.yaml +++ b/impl/test/src/test/resources/workflows-samples/call-http-post.yaml @@ -1,10 +1,10 @@ document: dsl: 1.0.0-alpha1 namespace: test - name: http-call-with-response-output + name: call-http-with-response-output version: 1.0.0 do: - - postPet: + - postAuthors: call: http with: method: post diff --git a/impl/test/src/test/resources/workflows-samples/call-http-put.yaml b/impl/test/src/test/resources/workflows-samples/call-http-put.yaml new file mode 100644 index 000000000..8567e64db --- /dev/null +++ b/impl/test/src/test/resources/workflows-samples/call-http-put.yaml @@ -0,0 +1,19 @@ +document: + dsl: 1.0.0-alpha1 + namespace: test + name: call-http-put + version: 1.0.0 +do: + - updateAuthor: + call: http + with: + redirect: true + headers: + content-type: application/json + accept: application/json + method: put + endpoint: + uri: https://fakerestapi.azurewebsites.net/api/v1/Authors/1 + body: "${{firstName: .firstName}}" + output: + as: .firstName \ No newline at end of file diff --git a/impl/test/src/test/resources/workflows-samples/call-http-redirect-false.yaml b/impl/test/src/test/resources/workflows-samples/call-http-redirect-false.yaml new file mode 100644 index 000000000..05cda7e60 --- /dev/null +++ b/impl/test/src/test/resources/workflows-samples/call-http-redirect-false.yaml @@ -0,0 +1,16 @@ +document: + dsl: 1.0.0-alpha1 + namespace: test + name: call-http-redirect-false + version: 1.0.0 +do: + - postUsersWithRedirectFalse: + call: http + with: + redirect: false + headers: + content-type: application/json + method: post + endpoint: + uri: http://localhost:9876/users + body: "${{firstName: .firstName, lastName: .lastName, id: .id, bookId: .bookId}}" \ No newline at end of file diff --git a/impl/test/src/test/resources/workflows-samples/call-with-response-output-expr.yaml b/impl/test/src/test/resources/workflows-samples/call-with-response-output-expr.yaml new file mode 100644 index 000000000..57579717d --- /dev/null +++ b/impl/test/src/test/resources/workflows-samples/call-with-response-output-expr.yaml @@ -0,0 +1,18 @@ +document: + dsl: 1.0.0-alpha1 + namespace: test + name: http-call-with-response-output-expr + version: 1.0.0 +do: + - postPet: + call: http + with: + redirect: true + headers: + content-type: application/json + method: post + endpoint: + uri: http://localhost:9876/users + body: "${{firstName: .firstName, lastName: .lastName, id: .id, bookId: .bookId}}" + output: + as: .status \ No newline at end of file diff --git a/impl/test/src/test/resources/workflows-samples/openapi/project-post-positive.yaml b/impl/test/src/test/resources/workflows-samples/openapi/project-post-positive.yaml index 89f97f1b2..1c5797105 100644 --- a/impl/test/src/test/resources/workflows-samples/openapi/project-post-positive.yaml +++ b/impl/test/src/test/resources/workflows-samples/openapi/project-post-positive.yaml @@ -21,4 +21,5 @@ do: validateOnly: false notifyMembers: true lang: en - Authorization: "Bearer eyJhbnNpc2l0b3IuYm9sdXMubWFnbnVz" \ No newline at end of file + Authorization: "Bearer eyJhbnNpc2l0b3IuYm9sdXMubWFnbnVz" + redirect: true \ No newline at end of file diff --git a/impl/test/src/test/resources/workflows-samples/try-catch-retry-inline.yaml b/impl/test/src/test/resources/workflows-samples/try-catch-retry-inline.yaml index 76037fec9..69dd3f2b0 100644 --- a/impl/test/src/test/resources/workflows-samples/try-catch-retry-inline.yaml +++ b/impl/test/src/test/resources/workflows-samples/try-catch-retry-inline.yaml @@ -11,6 +11,7 @@ do: with: method: get endpoint: http://localhost:9797 + redirect: true catch: errors: with: diff --git a/impl/test/src/test/resources/workflows-samples/try-catch-retry-reusable.yaml b/impl/test/src/test/resources/workflows-samples/try-catch-retry-reusable.yaml index ecf66a46c..00834c6f0 100644 --- a/impl/test/src/test/resources/workflows-samples/try-catch-retry-reusable.yaml +++ b/impl/test/src/test/resources/workflows-samples/try-catch-retry-reusable.yaml @@ -21,6 +21,7 @@ do: with: method: get endpoint: http://localhost:9797 + redirect: true catch: errors: with: From 5b06e0e09269693acdfd6ecb7824bd057edaf0ec Mon Sep 17 00:00:00 2001 From: Matheus Cruz Date: Wed, 26 Nov 2025 00:57:19 -0300 Subject: [PATCH 2/2] Standardize tests Signed-off-by: Matheus Cruz --- .../impl/test/HTTPWorkflowDefinitionTest.java | 237 ++++++++---------- 1 file changed, 105 insertions(+), 132 deletions(-) diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/HTTPWorkflowDefinitionTest.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/HTTPWorkflowDefinitionTest.java index 78b9431be..3591acaa2 100644 --- a/impl/test/src/test/java/io/serverlessworkflow/impl/test/HTTPWorkflowDefinitionTest.java +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/HTTPWorkflowDefinitionTest.java @@ -25,7 +25,6 @@ import java.io.IOException; import java.util.Map; import java.util.concurrent.CompletionException; -import java.util.stream.Stream; import mockwebserver3.MockResponse; import mockwebserver3.MockWebServer; import okhttp3.Headers; @@ -35,15 +34,10 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.ValueSource; public class HTTPWorkflowDefinitionTest { private static WorkflowApplication appl; - private static MockWebServer mockServer; @BeforeAll @@ -67,139 +61,138 @@ void shutdownServer() { mockServer.close(); } - @ParameterizedTest - @MethodSource("provideParameters") - void testWorkflowExecution( - String fileName, Object input, Runnable setup, Condition condition) - throws IOException { - setup.run(); - assertThat( - appl.workflowDefinition(readWorkflowFromClasspath(fileName)) - .instance(input) - .start() - .join()) - .is(condition); - } - - @ParameterizedTest - @ValueSource( - strings = { - "workflows-samples/call-http-query-parameters.yaml", - "workflows-samples/call-http-query-parameters-external-schema.yaml" - }) - void testWrongSchema(String fileName) { - IllegalArgumentException exception = - catchThrowableOfType( - IllegalArgumentException.class, - () -> appl.workflowDefinition(readWorkflowFromClasspath(fileName)).instance(Map.of())); - assertThat(exception) - .isNotNull() - .hasMessageContaining("There are JsonSchema validation errors"); - } - private static boolean httpCondition(WorkflowModel obj) { Map map = obj.asMap().orElseThrow(); return map.containsKey("photoUrls") || map.containsKey("petId"); } - private static Stream provideParameters() { - Map petInput = Map.of("petId", 10); - Map starTrekInput = Map.of("uid", "MOMA0000092393"); - Condition petCondition = - new Condition<>(HTTPWorkflowDefinitionTest::httpCondition, "callHttpCondition"); - Condition starTrekCondition = - new Condition<>( - o -> - ((Map) o.asMap().orElseThrow().get("movie")) - .get("title") - .equals("Star Trek"), - "StartTrek"); - Condition postCondition = - new Condition( - o -> o.asText().orElseThrow().equals("Javierito"), "CallHttpPostCondition"); - - Condition putCondition = - new Condition<>(o -> o.asText().get().contains("John"), "CallHttpPutCondition"); + @Test + void callHttpGet_should_return_pet_data() throws Exception { + WorkflowModel result = + appl.workflowDefinition(readWorkflowFromClasspath("workflows-samples/call-http-get.yaml")) + .instance(Map.of("petId", 10)) + .start() + .join(); + assertThat(result) + .has(new Condition<>(HTTPWorkflowDefinitionTest::httpCondition, "callHttpCondition")); + } - Condition patchCondition = - new Condition<>(o -> o.asText().get().contains("John"), "CallHttpPatchCondition"); + @Test + void callHttpGet_with_not_found_petId_should_keep_input_petId() throws Exception { + WorkflowModel result = + appl.workflowDefinition(readWorkflowFromClasspath("workflows-samples/call-http-get.yaml")) + .instance(Map.of("petId", "-1")) + .start() + .join(); + assertThat(result.asMap().orElseThrow()).containsKey("petId"); + } - Map postMap = Map.of("name", "Javierito", "surname", "Unknown"); - Map putMap = Map.of("firstName", "John"); + @Test + void callHttpEndpointInterpolation_should_work() throws Exception { + WorkflowModel result = + appl.workflowDefinition( + readWorkflowFromClasspath( + "workflows-samples/call-http-endpoint-interpolation.yaml")) + .instance(Map.of("petId", 10)) + .start() + .join(); + assertThat(result) + .has(new Condition<>(HTTPWorkflowDefinitionTest::httpCondition, "callHttpCondition")); + } - Runnable setupPost = - () -> - mockServer.enqueue( - new MockResponse( - 200, - Headers.of("Content-Type", "application/json"), - """ - { - "firstName": "Javierito" - } - """)); + @Test + void callHttpQueryParameters_should_find_star_trek_movie() throws Exception { + WorkflowModel result = + appl.workflowDefinition( + readWorkflowFromClasspath("workflows-samples/call-http-query-parameters.yaml")) + .instance(Map.of("uid", "MOMA0000092393")) + .start() + .join(); + assertThat(((Map) result.asMap().orElseThrow().get("movie")).get("title")) + .isEqualTo("Star Trek"); + } - return Stream.of( - Arguments.of("workflows-samples/call-http-get.yaml", petInput, doNothing, petCondition), - Arguments.of( - "workflows-samples/call-http-get.yaml", - Map.of("petId", "-1"), - doNothing, - new Condition( - o -> o.asMap().orElseThrow().containsKey("petId"), "notFoundCondition")), - Arguments.of( - "workflows-samples/call-http-endpoint-interpolation.yaml", - petInput, - doNothing, - petCondition), - Arguments.of( - "workflows-samples/call-http-query-parameters.yaml", - starTrekInput, - doNothing, - starTrekCondition), - Arguments.of( - "workflows-samples/call-http-find-by-status.yaml", - Map.of(), - doNothing, - new Condition(o -> !o.asCollection().isEmpty(), "HasElementCondition")), - Arguments.of( - "workflows-samples/call-http-query-parameters-external-schema.yaml", - starTrekInput, - doNothing, - starTrekCondition), - Arguments.of("workflows-samples/call-http-post.yaml", postMap, setupPost, postCondition), - Arguments.of( - "workflows-samples/call-http-delete.yaml", - Map.of(), - doNothing, - new Condition(o -> o.asMap().isEmpty(), "HTTP delete")), - Arguments.of("workflows-samples/call-http-put.yaml", putMap, doNothing, putCondition)); + @Test + void callHttpFindByStatus_should_return_non_empty_collection() throws Exception { + + WorkflowModel result = + appl.workflowDefinition( + readWorkflowFromClasspath("workflows-samples/call-http-find-by-status.yaml")) + .instance(Map.of()) + .start() + .join(); + assertThat(result.asCollection()).isNotEmpty(); } - private static final Runnable doNothing = () -> {}; + @Test + void callHttpQueryParameters_external_schema_should_find_star_trek() throws Exception { + WorkflowModel result = + appl.workflowDefinition( + readWorkflowFromClasspath( + "workflows-samples/call-http-query-parameters-external-schema.yaml")) + .instance(Map.of("uid", "MOMA0000092393")) + .start() + .join(); + assertThat(((Map) result.asMap().orElseThrow().get("movie")).get("title")) + .isEqualTo("Star Trek"); + } @Test - void post_should_run_call_http_with_expression_body() { + void callHttpPost_should_return_created_firstName() throws Exception { mockServer.enqueue( new MockResponse( 200, Headers.of("Content-Type", "application/json"), """ - { - "firstName": "Javierito" - } - """)); + { + "firstName": "Javierito" + } + """)); + WorkflowModel result = + appl.workflowDefinition(readWorkflowFromClasspath("workflows-samples/call-http-post.yaml")) + .instance(Map.of("name", "Javierito", "surname", "Unknown")) + .start() + .join(); + assertThat(result.asText().orElseThrow()).isEqualTo("Javierito"); + } + @Test + void testCallHttpDelete() { assertDoesNotThrow( () -> { appl.workflowDefinition( - readWorkflowFromClasspath("workflows-samples/call-http-post-expr.yaml")) - .instance(Map.of("name", "Javierito", "surname", "Unknown")) + readWorkflowFromClasspath("workflows-samples/call-http-delete.yaml")) + .instance(Map.of()) .start() .join(); }); } + @Test + void callHttpPut_should_contain_firstName_with_john() throws Exception { + WorkflowModel result = + appl.workflowDefinition(readWorkflowFromClasspath("workflows-samples/call-http-put.yaml")) + .instance(Map.of("firstName", "John")) + .start() + .join(); + assertThat(result.asText().orElseThrow()).contains("John"); + } + + @Test + void testWrongSchema_should_throw_illegal_argument() { + IllegalArgumentException exception = + catchThrowableOfType( + IllegalArgumentException.class, + () -> + appl.workflowDefinition( + readWorkflowFromClasspath( + "workflows-samples/call-http-query-parameters.yaml")) + .instance(Map.of())); + assertThat(exception) + .isNotNull() + .hasMessageContaining("There are JsonSchema validation errors"); + } + @Test void testHeadCall() { mockServer.enqueue( @@ -258,24 +251,4 @@ void testRedirectAsFalse() { .contains( "The property 'redirect' is set to false but received status 301 (Redirection); expected status in the 200-299 range"); } - - // @Test - // void testRedirectAsTrueWhenReceivingRedirection() { - // mockServer.enqueue( - // new MockResponse(301, Headers.of("Location", "http://localhost:9876/redirected"), "")); - // - // mockServer.enqueue( - // new MockResponse( - // 200, Headers.of("Content-Type", "application/json"), "{\"status\":\"OK\"}")); - // - // assertDoesNotThrow( - // () -> { - // appl.workflowDefinition( - // - // readWorkflowFromClasspath("workflows-samples/call-with-response-output-expr.yaml")) - // .instance(Map.of()) - // .start() - // .join(); - // }); - // } }