Repository: kestra-io/kestra
Issue: Implement if-else task

### Feature description

Currently, Kestra features the `io.kestra.core.tasks.flows.Switch` task acting as a value-based _switch_ statement. This allows diverting the execution path based on a resolved value. However, a simple binary conditional requires a lot of boilerplate code.

The current approach to execute a simple task conditionally is illustrated bellow:

```yaml
  - id: run-X-when-necessary
    type: io.kestra.core.tasks.flows.Switch
    value: "{{ inputs contains 'aVariableConnectedToX' ? 'RUN' : 'SKIP' }}"
    cases:
      RUN:
        - id: run-X
          type: io.kestra.core.tasks.debugs.Echo
          description: "Run X"
          format: "Running X with {{ inputs.aVariableConnectedToX }}..."
    defaults:
      - id: skipping-X
        type: io.kestra.core.tasks.debugs.Echo
        description: "Switch requires to have a task to execute"
        format: "Skipping X..."
```

It would be great to have a simple task acting as the classic _if-else_ statement allowing the following notation:
```yaml
- id: run-X-when-necessary
  type: io.kestra.core.tasks.flows.If
  test: "{{ inputs contains 'aVariableConnectedToX' }}"
  then:
    - id: run-X
      type: io.kestra.core.tasks.debugs.Echo
      description: "Run X"
      format: "Running X with {{ inputs.aVariableConnectedToX }}..."
```
or
```yaml
- id: run-X-when-necessary
  type: io.kestra.core.tasks.flows.If
  test: "{{ inputs contains 'aVariableConnectedToX' }}"
  then:
    - id: run-X
      type: io.kestra.core.tasks.debugs.Echo
      description: "Run X"
      format: "Running X with {{ inputs.aVariableConnectedToX }}..."
  else:
    - id: run-Y
      type: io.kestra.core.tasks.debugs.Echo
      description: "Run Y"
      format: "Running Y..."
```

The `test` condition should use a _truth_ value - empty string being evaluated to false, etc.

Issue comments:

Pull request review comments:
there is no null possible in pebble?
```suggestion
    private List<Task> tasks;
```
add another unit test without else please
add `@NotEmpty` (or whatever meaning size > 0) 
No, it generates an error so I had to do it this way
I mean `List.of("false", "0", "-0", "", "null")`, not sure it exists 
Done, and yes, there was an issue ;)
Done

Patch that resolved the issue:
diff --git a/core/src/main/java/io/kestra/core/services/GraphService.java b/core/src/main/java/io/kestra/core/services/GraphService.java
index 8cad220a3f..c20a99c666 100644
--- a/core/src/main/java/io/kestra/core/services/GraphService.java
+++ b/core/src/main/java/io/kestra/core/services/GraphService.java
@@ -167,6 +167,25 @@ public static void switchCase(
         }
     }
 
+    public static void ifElse(
+        GraphCluster graph,
+        List<Task> then,
+        List<Task> _else,
+        List<Task> errors,
+        TaskRun parent,
+        Execution execution
+    ) throws IllegalVariableEvaluationException {
+        fillGraph(graph, then, RelationType.SEQUENTIAL, parent, execution, "then");
+        if (_else != null) {
+            fillGraph(graph, _else, RelationType.SEQUENTIAL, parent, execution, "else");
+        }
+
+        // error cases
+        if (errors != null && errors.size() > 0) {
+            fillGraph(graph, errors, RelationType.ERROR, parent, execution, null);
+        }
+    }
+
     private static void iterate(
         GraphCluster graph,
         List<Task> tasks,
diff --git a/core/src/main/java/io/kestra/core/tasks/executions/Fail.java b/core/src/main/java/io/kestra/core/tasks/executions/Fail.java
index d9182d3b5b..87fa06c355 100644
--- a/core/src/main/java/io/kestra/core/tasks/executions/Fail.java
+++ b/core/src/main/java/io/kestra/core/tasks/executions/Fail.java
@@ -7,6 +7,7 @@
 import io.kestra.core.models.tasks.Task;
 import io.kestra.core.models.tasks.VoidOutput;
 import io.kestra.core.runners.RunContext;
+import io.kestra.core.utils.TruthUtils;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Builder;
 import lombok.EqualsAndHashCode;
@@ -85,7 +86,10 @@
 public class Fail extends Task implements RunnableTask<VoidOutput> {
 
     @PluginProperty(dynamic = true)
-    @Schema(title = "Optional condition, must evaluate to a boolean.")
+    @Schema(
+        title = "Optional condition, must coerce to a boolean.",
+        description = "Boolean coercion allows 0, -0, and '' to coerce to false, all other values to coerce to true."
+    )
     private String condition;
 
     @PluginProperty(dynamic = true)
@@ -97,7 +101,7 @@ public class Fail extends Task implements RunnableTask<VoidOutput> {
     public VoidOutput run(RunContext runContext) throws Exception {
         if (condition != null) {
             String rendered = runContext.render(condition);
-            if (Boolean.parseBoolean(rendered)) {
+            if (TruthUtils.isTruthy(rendered)) {
                 runContext.logger().error(runContext.render(errorMessage));
                 throw new RuntimeException("Fail on a condition");
             }
diff --git a/core/src/main/java/io/kestra/core/tasks/flows/If.java b/core/src/main/java/io/kestra/core/tasks/flows/If.java
new file mode 100644
index 0000000000..b0153d71a9
--- /dev/null
+++ b/core/src/main/java/io/kestra/core/tasks/flows/If.java
@@ -0,0 +1,175 @@
+package io.kestra.core.tasks.flows;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.collect.ImmutableMap;
+import io.kestra.core.exceptions.IllegalVariableEvaluationException;
+import io.kestra.core.models.annotations.Example;
+import io.kestra.core.models.annotations.Plugin;
+import io.kestra.core.models.annotations.PluginProperty;
+import io.kestra.core.models.executions.Execution;
+import io.kestra.core.models.executions.NextTaskRun;
+import io.kestra.core.models.executions.TaskRun;
+import io.kestra.core.models.flows.State;
+import io.kestra.core.models.hierarchies.GraphCluster;
+import io.kestra.core.models.hierarchies.RelationType;
+import io.kestra.core.models.tasks.FlowableTask;
+import io.kestra.core.models.tasks.ResolvedTask;
+import io.kestra.core.models.tasks.Task;
+import io.kestra.core.models.tasks.VoidOutput;
+import io.kestra.core.runners.FlowableUtils;
+import io.kestra.core.runners.RunContext;
+import io.kestra.core.services.GraphService;
+import io.kestra.core.utils.TruthUtils;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import lombok.experimental.SuperBuilder;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.validation.Valid;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@SuperBuilder
+@ToString
+@EqualsAndHashCode
+@Getter
+@NoArgsConstructor
+@Schema(
+    title = "Process some tasks conditionally depending on a contextual value",
+    description = "Allow some workflow based on context variables, for example branch a flow based on a previous task."
+)
+@Plugin(
+    examples = {
+        @Example(
+            full = true,
+            code = {
+                "id: if",
+                "namespace: io.kestra.tests",
+                "",
+                "inputs:",
+                "  - name: string",
+                "    type: STRING",
+                "    required: true",
+                "",
+                "tasks:",
+                "  - id: if",
+                "    type: io.kestra.core.tasks.flows.If",
+                "    condition: \"{{inputs.string == 'Condition'}}\"",
+                "    then:",
+                "      - id: when-true",
+                "        type: io.kestra.core.tasks.log.Log",
+                "        message: 'Condition was true'",
+                "    else:",
+                "      - id: when-false",
+                "        type: io.kestra.core.tasks.log.Log",
+                "        message: 'Condition was false'",
+            }
+        )
+    }
+)
+public class If extends Task implements FlowableTask<VoidOutput> {
+    @PluginProperty(dynamic = true)
+    @Schema(
+        title = "If condition, must coerce to a boolean.",
+        description = "Boolean coercion allows 0, -0, null and '' to coerce to false,  all other values to coerce to true."
+    )
+    private String condition;
+
+    @Valid
+    @PluginProperty
+    @Schema(
+        title = "List of tasks to execute when the condition is true."
+    )
+    @NotEmpty
+    private List<Task> then;
+
+    @Valid
+    @PluginProperty
+    @Schema(
+        title = "List of tasks to execute when the condition is false."
+    )
+    @JsonProperty("else")
+    private List<Task> _else;
+
+    @Valid
+    @PluginProperty
+    @Schema(
+        title = "List of tasks to execute in case of errors on a child task."
+    )
+    private List<Task> errors;
+
+    @Override
+    public List<Task> getErrors() {
+        return errors;
+    }
+
+    @Override
+    public GraphCluster tasksTree(Execution execution, TaskRun taskRun, List<String> parentValues) throws IllegalVariableEvaluationException {
+        GraphCluster subGraph = new GraphCluster(this, taskRun, parentValues, RelationType.CHOICE);
+
+        GraphService.ifElse(
+            subGraph,
+            this.then,
+            this._else,
+            this.errors,
+            taskRun,
+            execution
+        );
+
+        return subGraph;
+    }
+
+    @Override
+    public List<Task> allChildTasks() {
+        return Stream
+            .concat(
+                this.then.stream(),
+                Stream.concat(
+                    this._else != null ? this._else.stream() : Stream.empty(),
+                    this.errors != null ? this.errors.stream() : Stream.empty())
+            )
+            .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<ResolvedTask> childTasks(RunContext runContext, TaskRun parentTaskRun) throws IllegalVariableEvaluationException {
+        String rendered = runContext.render(condition);
+        if (TruthUtils.isTruthy(rendered)) {
+            return FlowableUtils.resolveTasks(then, parentTaskRun);
+        }
+        return FlowableUtils.resolveTasks(_else, parentTaskRun);
+    }
+
+    @Override
+    public List<NextTaskRun> resolveNexts(RunContext runContext, Execution execution, TaskRun parentTaskRun) throws IllegalVariableEvaluationException {
+        return FlowableUtils.resolveSequentialNexts(
+            execution,
+            this.childTasks(runContext, parentTaskRun),
+            FlowableUtils.resolveTasks(this.errors, parentTaskRun),
+            parentTaskRun
+        );
+    }
+
+    @Override
+    public Optional<State.Type> resolveState(RunContext runContext, Execution execution, TaskRun parentTaskRun) throws IllegalVariableEvaluationException {
+        List<ResolvedTask> childTask = this.childTasks(runContext, parentTaskRun);
+        if (childTask == null) {
+            // no next task to run, we guess the state from the parent task
+            return Optional.of(execution.guessFinalState(null, parentTaskRun));
+        }
+
+        return FlowableUtils.resolveState(
+            execution,
+            this.childTasks(runContext, parentTaskRun),
+            FlowableUtils.resolveTasks(this.getErrors(), parentTaskRun),
+            parentTaskRun,
+            runContext
+        );
+    }
+}
diff --git a/core/src/main/java/io/kestra/core/utils/TruthUtils.java b/core/src/main/java/io/kestra/core/utils/TruthUtils.java
new file mode 100644
index 0000000000..8764789b00
--- /dev/null
+++ b/core/src/main/java/io/kestra/core/utils/TruthUtils.java
@@ -0,0 +1,11 @@
+package io.kestra.core.utils;
+
+import java.util.List;
+
+abstract public class TruthUtils {
+    private static final List<String> FALSE_VALUES = List.of("false", "0", "-0", "");
+
+    public static boolean isTruthy(String condition) {
+        return condition != null && !FALSE_VALUES.contains(condition);
+    }
+}
diff --git a/core/src/main/resources/icons/io.kestra.core.tasks.flows.If.svg b/core/src/main/resources/icons/io.kestra.core.tasks.flows.If.svg
new file mode 100644
index 0000000000..a6d077d33a
--- /dev/null
+++ b/core/src/main/resources/icons/io.kestra.core.tasks.flows.If.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="700pt" height="700pt" version="1.1" viewBox="0 0 700 700" xmlns="http://www.w3.org/2000/svg">
+ <g>
+  <path d="m525 525c-9.6641 0-17.5-7.8281-17.5-17.5s7.8359-17.5 17.5-17.5c9.6484 0 17.5-7.8438 17.5-17.5v-20.508c0-11.723 3.8203-22.867 10.871-31.992-7.0508-9.125-10.871-20.27-10.871-31.992v-20.508c0-9.6562-7.8516-17.5-17.5-17.5-9.6641 0-17.5-7.8281-17.5-17.5s7.8359-17.5 17.5-17.5c28.949 0 52.5 23.551 52.5 52.5v20.508c0 4.5977 1.8711 9.1094 5.1289 12.375l7.2461 7.2461c6.8359 6.8359 6.8359 17.91 0 24.746l-7.2461 7.2461c-3.2578 3.2617-5.1289 7.7734-5.1289 12.371v20.508c0 28.949-23.551 52.5-52.5 52.5z"/>
+  <path d="m455 525c-28.949 0-52.5-23.551-52.5-52.5v-20.508c0-4.5977-1.8711-9.1094-5.1289-12.375l-7.2461-7.2461c-6.8359-6.8359-6.8359-17.91 0-24.746l7.2461-7.2461c3.2578-3.2617 5.1289-7.7734 5.1289-12.371v-20.508c0-28.949 23.551-52.5 52.5-52.5 9.6641 0 17.5 7.8281 17.5 17.5s-7.8359 17.5-17.5 17.5c-9.6484 0-17.5 7.8438-17.5 17.5v20.508c0 11.723-3.8203 22.867-10.867 31.992 7.0469 9.125 10.867 20.27 10.867 31.992v20.508c0 9.6562 7.8516 17.5 17.5 17.5 9.6641 0 17.5 7.8281 17.5 17.5s-7.8359 17.5-17.5 17.5z"/>
+  <path d="m245 525c-9.6641 0-17.5-7.8281-17.5-17.5s7.8359-17.5 17.5-17.5c9.6484 0 17.5-7.8438 17.5-17.5v-20.508c0-11.723 3.8203-22.867 10.871-31.992-7.0508-9.125-10.871-20.27-10.871-31.992v-20.508c0-9.6562-7.8516-17.5-17.5-17.5-9.6641 0-17.5-7.8281-17.5-17.5s7.8359-17.5 17.5-17.5c28.949 0 52.5 23.551 52.5 52.5v20.508c0 4.5977 1.8711 9.1094 5.1289 12.375l7.2461 7.2461c6.8359 6.8359 6.8359 17.91 0 24.746l-7.2461 7.2461c-3.2578 3.2617-5.1289 7.7734-5.1289 12.371v20.508c0 28.949-23.551 52.5-52.5 52.5z"/>
+  <path d="m175 525c-28.949 0-52.5-23.551-52.5-52.5v-20.508c0-4.5977-1.8711-9.1094-5.1289-12.375l-7.2461-7.2461c-6.8359-6.8359-6.8359-17.91 0-24.746l7.2461-7.2461c3.2578-3.2617 5.1289-7.7734 5.1289-12.371v-20.508c0-28.949 23.551-52.5 52.5-52.5 9.6641 0 17.5 7.8281 17.5 17.5s-7.8359 17.5-17.5 17.5c-9.6484 0-17.5 7.8438-17.5 17.5v20.508c0 11.723-3.8203 22.867-10.867 31.992 7.0469 9.125 10.867 20.27 10.867 31.992v20.508c0 9.6562 7.8516 17.5 17.5 17.5 9.6641 0 17.5 7.8281 17.5 17.5s-7.8359 17.5-17.5 17.5z"/>
+  <path d="m227.5 472.5c-4.4766 0-8.957-1.7109-12.375-5.1289l-35-35c-6.8359-6.8359-6.8359-17.91 0-24.746l35-35c6.8359-6.8359 17.91-6.8359 24.746 0 6.8359 6.8359 6.8359 17.91 0 24.746l-22.625 22.629 22.629 22.629c6.8359 6.8359 6.8359 17.91 0 24.746-3.418 3.418-7.8984 5.125-12.375 5.125z"/>
+  <path d="m472.5 472.5c-4.4766 0-8.957-1.7109-12.375-5.1289-6.8359-6.8359-6.8359-17.91 0-24.746l22.629-22.625-22.629-22.629c-6.8359-6.8359-6.8359-17.91 0-24.746s17.91-6.8359 24.746 0l35 35c6.8359 6.8359 6.8359 17.91 0 24.746l-35 35c-3.4141 3.4219-7.8945 5.1289-12.371 5.1289z"/>
+  <path d="m192.5 315h35v-35h35c9.6641 0 17.5-7.8359 17.5-17.5v-52.5h-35v35h-35c-9.6641 0-17.5 7.8359-17.5 17.5z"/>
+  <path d="m507.5 315h-35v-35h-35c-9.6641 0-17.5-7.8359-17.5-17.5v-52.5h35v35h35c9.6641 0 17.5 7.8359 17.5 17.5z"/>
+  <path d="m437.5 35h-175c-19.328 0-35 15.672-35 35v87.5c0 19.328 15.672 35 35 35h70v17.5h-17.5c-9.6719 0-17.5 7.8359-17.5 17.5s7.8281 17.5 17.5 17.5h70c9.6719 0 17.5-7.8359 17.5-17.5s-7.8281-17.5-17.5-17.5h-17.5v-17.5h70c19.328 0 35-15.672 35-35v-87.5c0-19.328-15.672-35-35-35zm-108.5 106.74c3.8711 2.9062 4.6562 8.3906 1.75 12.254-1.7148 2.2891-4.3398 3.5039-7.0039 3.5039-1.8281 0-3.6641-0.5625-5.2383-1.7422-13.348-10.016-21.004-25.328-21.004-42.008s7.6562-31.992 21.004-42.008c3.8555-2.8867 9.332-2.0859 12.246 1.7617 2.9062 3.8633 2.1211 9.3477-1.75 12.254-8.8984 6.6641-14 16.867-14 27.992s5.1016 21.328 13.996 27.992zm52.5 14.016c-1.5703 1.1797-3.4102 1.7422-5.2383 1.7422-2.668 0-5.2891-1.2148-7.0078-3.5039-2.9062-3.8633-2.1211-9.3477 1.75-12.254 8.8984-6.6641 14-16.867 14-27.992s-5.1016-21.328-13.996-27.992c-3.8711-2.9062-4.6562-8.3906-1.75-12.254 2.9141-3.8438 8.3906-4.6484 12.246-1.7617 13.344 10.016 21 25.328 21 42.008s-7.6562 31.992-21.004 42.008z"/>
+ </g>
+</svg>


Test patch:
diff --git a/core/src/test/java/io/kestra/core/Helpers.java b/core/src/test/java/io/kestra/core/Helpers.java
index 62e15377b2..82bd964bb3 100644
--- a/core/src/test/java/io/kestra/core/Helpers.java
+++ b/core/src/test/java/io/kestra/core/Helpers.java
@@ -19,7 +19,7 @@
 import java.util.function.Consumer;
 
 public class Helpers {
-    public static long FLOWS_COUNT = 61;
+    public static long FLOWS_COUNT = 63;
 
     public static ApplicationContext applicationContext() throws URISyntaxException {
         return applicationContext(
diff --git a/core/src/test/java/io/kestra/core/tasks/flows/IfTest.java b/core/src/test/java/io/kestra/core/tasks/flows/IfTest.java
new file mode 100644
index 0000000000..710f6a1b91
--- /dev/null
+++ b/core/src/test/java/io/kestra/core/tasks/flows/IfTest.java
@@ -0,0 +1,88 @@
+package io.kestra.core.tasks.flows;
+
+import io.kestra.core.models.executions.Execution;
+import io.kestra.core.models.flows.State;
+import io.kestra.core.runners.AbstractMemoryRunnerTest;
+import org.junit.jupiter.api.Test;
+
+import java.time.Duration;
+import java.util.Map;
+import java.util.concurrent.TimeoutException;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+
+class IfTest  extends AbstractMemoryRunnerTest {
+    @Test
+    void ifTruthy() throws TimeoutException {
+        Execution execution = runnerUtils.runOne("io.kestra.tests", "if-condition", null,
+            (f, e) -> Map.of("param", true) , Duration.ofSeconds(120));
+
+        assertThat(execution.getTaskRunList(), hasSize(2));
+        assertThat(execution.findTaskRunsByTaskId("when-true").get(0).getState().getCurrent(), is(State.Type.SUCCESS));
+        assertThat(execution.getState().getCurrent(), is(State.Type.SUCCESS));
+
+        execution = runnerUtils.runOne("io.kestra.tests", "if-condition", null,
+            (f, e) -> Map.of("param", "true") , Duration.ofSeconds(120));
+
+        assertThat(execution.getTaskRunList(), hasSize(2));
+        assertThat(execution.findTaskRunsByTaskId("when-true").get(0).getState().getCurrent(), is(State.Type.SUCCESS));
+        assertThat(execution.getState().getCurrent(), is(State.Type.SUCCESS));
+
+        execution = runnerUtils.runOne("io.kestra.tests", "if-condition", null,
+            (f, e) -> Map.of("param", 1) , Duration.ofSeconds(120));
+
+        assertThat(execution.getTaskRunList(), hasSize(2));
+        assertThat(execution.findTaskRunsByTaskId("when-true").get(0).getState().getCurrent(), is(State.Type.SUCCESS));
+        assertThat(execution.getState().getCurrent(), is(State.Type.SUCCESS));
+    }
+
+    @Test
+    void ifFalsy() throws TimeoutException {
+        Execution execution = runnerUtils.runOne("io.kestra.tests", "if-condition", null,
+            (f, e) -> Map.of("param", false) , Duration.ofSeconds(120));
+
+        assertThat(execution.getTaskRunList(), hasSize(2));
+        assertThat(execution.findTaskRunsByTaskId("when-false").get(0).getState().getCurrent(), is(State.Type.SUCCESS));
+        assertThat(execution.getState().getCurrent(), is(State.Type.SUCCESS));
+
+        execution = runnerUtils.runOne("io.kestra.tests", "if-condition", null,
+            (f, e) -> Map.of("param", "false") , Duration.ofSeconds(120));
+
+        assertThat(execution.getTaskRunList(), hasSize(2));
+        assertThat(execution.findTaskRunsByTaskId("when-false").get(0).getState().getCurrent(), is(State.Type.SUCCESS));
+        assertThat(execution.getState().getCurrent(), is(State.Type.SUCCESS));
+
+        execution = runnerUtils.runOne("io.kestra.tests", "if-condition", null,
+            (f, e) -> Map.of("param", 0) , Duration.ofSeconds(120));
+
+        assertThat(execution.getTaskRunList(), hasSize(2));
+        assertThat(execution.findTaskRunsByTaskId("when-false").get(0).getState().getCurrent(), is(State.Type.SUCCESS));
+        assertThat(execution.getState().getCurrent(), is(State.Type.SUCCESS));
+
+        execution = runnerUtils.runOne("io.kestra.tests", "if-condition", null,
+            (f, e) -> Map.of("param", -0) , Duration.ofSeconds(120));
+
+        assertThat(execution.getTaskRunList(), hasSize(2));
+        assertThat(execution.findTaskRunsByTaskId("when-false").get(0).getState().getCurrent(), is(State.Type.SUCCESS));
+        assertThat(execution.getState().getCurrent(), is(State.Type.SUCCESS));
+
+        // We cannot test null as inputs cannot be null
+    }
+    
+    @Test
+    void ifWithoutElse() throws TimeoutException {
+        Execution execution = runnerUtils.runOne("io.kestra.tests", "if-without-else", null,
+            (f, e) -> Map.of("param", true) , Duration.ofSeconds(120));
+
+        assertThat(execution.getTaskRunList(), hasSize(2));
+        assertThat(execution.findTaskRunsByTaskId("when-true").get(0).getState().getCurrent(), is(State.Type.SUCCESS));
+        assertThat(execution.getState().getCurrent(), is(State.Type.SUCCESS));
+
+        execution = runnerUtils.runOne("io.kestra.tests", "if-without-else", null,
+            (f, e) -> Map.of("param", false) , Duration.ofSeconds(120));
+        assertThat(execution.getTaskRunList(), hasSize(1));
+        assertThat(execution.findTaskRunsByTaskId("when-true").isEmpty(), is(true));
+        assertThat(execution.getState().getCurrent(), is(State.Type.SUCCESS));
+    }
+}
\ No newline at end of file
diff --git a/core/src/test/resources/flows/valids/if-condition.yaml b/core/src/test/resources/flows/valids/if-condition.yaml
new file mode 100644
index 0000000000..f3c2ce0d03
--- /dev/null
+++ b/core/src/test/resources/flows/valids/if-condition.yaml
@@ -0,0 +1,19 @@
+id: if-condition
+namespace: io.kestra.tests
+
+inputs:
+  - name: param
+    type: STRING
+
+tasks:
+  - id: if
+    type: io.kestra.core.tasks.flows.If
+    condition: "{{inputs.param}}"
+    then:
+      - id: when-true
+        type: io.kestra.core.tasks.log.Log
+        message: 'Condition was true'
+    else:
+      - id: when-false
+        type: io.kestra.core.tasks.log.Log
+        message: 'Condition was false'
\ No newline at end of file
diff --git a/core/src/test/resources/flows/valids/if-without-else.yaml b/core/src/test/resources/flows/valids/if-without-else.yaml
new file mode 100644
index 0000000000..9dd6a917c9
--- /dev/null
+++ b/core/src/test/resources/flows/valids/if-without-else.yaml
@@ -0,0 +1,15 @@
+id: if-without-else
+namespace: io.kestra.tests
+
+inputs:
+  - name: param
+    type: STRING
+
+tasks:
+  - id: if
+    type: io.kestra.core.tasks.flows.If
+    condition: "{{inputs.param}}"
+    then:
+      - id: when-true
+        type: io.kestra.core.tasks.log.Log
+        message: 'Condition was true'
\ No newline at end of file