Repository: kestra-io/kestra
Issue: Migrate webserver test from memory to H2

### Issue description

Since many endpoints are not implemented in the memory repositories, they cannot be tested.
We need to rewrite the test to work with a H2 database and add the missing tests

Issue comments:

Pull request review comments:
```suggestion
    testImplementation project(':runner-memory')
```

This should be removed to prove it's working ;)
You should only need H2
Well, I prefere to keep those warnings but ... OK-ish
We've used them over 100 times in the application, so I don't see the need for spam to tell us that we're doing unchecked cast unless we plan to correct it in the short term.
No, because there are utils I need in them
Is it really needed ?
We shouldn't normally have two implementations on the same application context.

Patch that resolved the issue:
diff --git a/jdbc-h2/src/main/java/io/kestra/repository/h2/H2SettingRepository.java b/jdbc-h2/src/main/java/io/kestra/repository/h2/H2SettingRepository.java
index 27170a4a27..4cb1c17b24 100644
--- a/jdbc-h2/src/main/java/io/kestra/repository/h2/H2SettingRepository.java
+++ b/jdbc-h2/src/main/java/io/kestra/repository/h2/H2SettingRepository.java
@@ -1,9 +1,7 @@
 package io.kestra.repository.h2;
 
 import io.kestra.core.models.Setting;
-import io.kestra.core.models.triggers.Trigger;
 import io.kestra.jdbc.repository.AbstractJdbcSettingRepository;
-import io.kestra.jdbc.repository.AbstractJdbcTriggerRepository;
 import io.micronaut.context.ApplicationContext;
 import jakarta.inject.Inject;
 import jakarta.inject.Singleton;
diff --git a/webserver/build.gradle b/webserver/build.gradle
index 47b399d581..d0f2c204b9 100644
--- a/webserver/build.gradle
+++ b/webserver/build.gradle
@@ -22,9 +22,12 @@ dependencies {
 
     // test
     testImplementation project(':core').sourceSets.test.output
-    testImplementation project(':repository-memory')
-    testImplementation project(':runner-memory')
     testImplementation project(':storage-local')
     testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.0")
+
+    testImplementation project(':jdbc')
+    testImplementation project(':jdbc').sourceSets.test.output
+    testImplementation project(':jdbc-h2')
+    testImplementation("io.micronaut.sql:micronaut-jooq")
 }
 


Test patch:
diff --git a/webserver/src/test/java/io/kestra/webserver/controllers/BlueprintControllerTest.java b/webserver/src/test/java/io/kestra/webserver/controllers/BlueprintControllerTest.java
index 15740e77eb..7c496b03a9 100644
--- a/webserver/src/test/java/io/kestra/webserver/controllers/BlueprintControllerTest.java
+++ b/webserver/src/test/java/io/kestra/webserver/controllers/BlueprintControllerTest.java
@@ -3,7 +3,6 @@
 import com.github.tomakehurst.wiremock.client.WireMock;
 import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
 import com.github.tomakehurst.wiremock.junit5.WireMockTest;
-import io.kestra.core.models.hierarchies.FlowGraph;
 import io.kestra.core.repositories.ArrayListTotal;
 import io.kestra.webserver.responses.PagedResults;
 import io.micronaut.core.type.Argument;
@@ -77,6 +76,7 @@ void blueprintFlow(WireMockRuntimeInfo wmRuntimeInfo) {
         wireMock.verifyThat(getRequestedFor(urlEqualTo("/v1/blueprints/id_1/flow")));
     }
 
+    @SuppressWarnings("unchecked")
     @Test
     void blueprintGraph(WireMockRuntimeInfo wmRuntimeInfo) {
         stubFor(get(urlMatching("/v1/blueprints/id_1/graph.*"))
diff --git a/webserver/src/test/java/io/kestra/webserver/controllers/ExecutionControllerTest.java b/webserver/src/test/java/io/kestra/webserver/controllers/ExecutionControllerTest.java
index cb1b41c280..7a5b5ff868 100644
--- a/webserver/src/test/java/io/kestra/webserver/controllers/ExecutionControllerTest.java
+++ b/webserver/src/test/java/io/kestra/webserver/controllers/ExecutionControllerTest.java
@@ -3,19 +3,19 @@
 import com.google.common.collect.ImmutableMap;
 import io.kestra.core.models.Label;
 import io.kestra.core.models.executions.Execution;
-import io.kestra.core.models.executions.TaskRun;
 import io.kestra.core.models.flows.Flow;
 import io.kestra.core.models.flows.State;
 import io.kestra.core.models.storage.FileMetas;
 import io.kestra.core.models.triggers.types.Webhook;
+import io.kestra.core.models.executions.TaskRun;
 import io.kestra.core.queues.QueueFactoryInterface;
 import io.kestra.core.queues.QueueInterface;
 import io.kestra.core.repositories.ExecutionRepositoryInterface;
 import io.kestra.core.repositories.FlowRepositoryInterface;
-import io.kestra.core.runners.AbstractMemoryRunnerTest;
 import io.kestra.core.runners.InputsTest;
 import io.kestra.core.utils.Await;
 import io.kestra.core.utils.IdUtils;
+import io.kestra.webserver.controllers.h2.JdbcH2ControllerTest;
 import io.kestra.webserver.responses.PagedResults;
 import io.micronaut.core.type.Argument;
 import io.micronaut.data.model.Pageable;
@@ -45,7 +45,7 @@
 import static org.hamcrest.Matchers.*;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
-class ExecutionControllerTest extends AbstractMemoryRunnerTest {
+class ExecutionControllerTest extends JdbcH2ControllerTest {
     @Inject
     EmbeddedServer embeddedServer;
 
@@ -92,8 +92,6 @@ private Execution triggerExecution(String namespace, String flowId, MultipartBod
             Execution.class
         );
     }
-
-
     private MultipartBody createInputsFlowBody() {
         // Trigger execution
         File applicationFile = new File(Objects.requireNonNull(
@@ -434,7 +432,7 @@ void downloadFile() throws TimeoutException {
             FileMetas.class
         ).blockingFirst();
 
-        assertThat(metas.getSize(), equalTo(648L));
+        assertThat(metas.getSize(), equalTo(2193L));
 
         String newExecutionId = IdUtils.create();
 
@@ -551,4 +549,14 @@ void killPaused() throws TimeoutException, InterruptedException {
             Execution.class);
         assertThat(execution.getState().isPaused(), is(false));
     }
+
+    @Test
+    void find() throws TimeoutException, InterruptedException {
+        PagedResults<?> executions = client.toBlocking().retrieve(
+            HttpRequest.GET("/api/v1/executions/search"), PagedResults.class
+        );
+
+        assertThat(executions.getTotal(), is(0L));
+
+    }
 }
diff --git a/webserver/src/test/java/io/kestra/webserver/controllers/FlowControllerTest.java b/webserver/src/test/java/io/kestra/webserver/controllers/FlowControllerTest.java
index 596630f4b4..f0620cd518 100644
--- a/webserver/src/test/java/io/kestra/webserver/controllers/FlowControllerTest.java
+++ b/webserver/src/test/java/io/kestra/webserver/controllers/FlowControllerTest.java
@@ -10,14 +10,14 @@
 import io.kestra.core.models.hierarchies.FlowGraph;
 import io.kestra.core.models.tasks.Task;
 import io.kestra.core.models.validations.ValidateConstraintViolation;
-import io.kestra.core.runners.AbstractMemoryRunnerTest;
 import io.kestra.core.serializers.YamlFlowParser;
 import io.kestra.core.tasks.debugs.Return;
 import io.kestra.core.tasks.flows.Sequential;
 import io.kestra.core.utils.IdUtils;
 import io.kestra.core.utils.TestsUtils;
-import io.kestra.repository.memory.MemoryFlowRepository;
+import io.kestra.jdbc.repository.AbstractJdbcFlowRepository;
 import io.kestra.webserver.controllers.domain.IdWithNamespace;
+import io.kestra.webserver.controllers.h2.JdbcH2ControllerTest;
 import io.kestra.webserver.responses.BulkResponse;
 import io.kestra.webserver.responses.PagedResults;
 import io.micronaut.core.type.Argument;
@@ -37,7 +37,6 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.net.URISyntaxException;
 import java.net.URL;
 import java.nio.charset.Charset;
 import java.nio.file.Files;
@@ -51,22 +50,20 @@
 import static org.hamcrest.Matchers.*;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
-class FlowControllerTest extends AbstractMemoryRunnerTest {
+class FlowControllerTest extends JdbcH2ControllerTest {
     @Inject
     @Client("/")
     RxHttpClient client;
 
     @Inject
-    MemoryFlowRepository memoryFlowRepository;
+    AbstractJdbcFlowRepository jdbcFlowRepository;
 
     @BeforeEach
-    protected void init() throws IOException, URISyntaxException {
-        memoryFlowRepository.findAll()
-            .forEach(memoryFlowRepository::delete);
+    protected void init() {
+        jdbcFlowRepository.findAll()
+            .forEach(jdbcFlowRepository::delete);
 
-        super.init();
-
-        TestsUtils.loads(repositoryLoader);
+        super.setup();
     }
 
     @Test
@@ -154,8 +151,8 @@ void updateNamespace() {
         // f3 & f4 must be updated
         updated = client.toBlocking().retrieve(HttpRequest.POST("/api/v1/flows/io.kestra.updatenamespace", flows), Argument.listOf(Flow.class));
         assertThat(updated.size(), is(4));
-        assertThat(updated.get(0).getInputs().get(0).getName(), is("2"));
-        assertThat(updated.get(1).getInputs().get(0).getName(), is("1"));
+        assertThat(updated.get(2).getInputs().get(0).getName(), is("3-3"));
+        assertThat(updated.get(3).getInputs().get(0).getName(), is("4"));
 
         // f1 & f2 must be deleted
         assertThrows(HttpClientResponseException.class, () -> {
diff --git a/webserver/src/test/java/io/kestra/webserver/controllers/MetricControllerTest.java b/webserver/src/test/java/io/kestra/webserver/controllers/MetricControllerTest.java
index 789ea894de..15081d193d 100644
--- a/webserver/src/test/java/io/kestra/webserver/controllers/MetricControllerTest.java
+++ b/webserver/src/test/java/io/kestra/webserver/controllers/MetricControllerTest.java
@@ -2,9 +2,8 @@
 
 import io.kestra.core.models.executions.Execution;
 import io.kestra.core.models.executions.MetricEntry;
-import io.kestra.core.repositories.ArrayListTotal;
-import io.kestra.core.runners.AbstractMemoryRunnerTest;
-import io.kestra.repository.memory.MemoryMetricRepository;
+import io.kestra.jdbc.repository.AbstractJdbcMetricRepository;
+import io.kestra.webserver.controllers.h2.JdbcH2ControllerTest;
 import io.kestra.webserver.responses.PagedResults;
 import io.micronaut.core.type.Argument;
 import io.micronaut.http.HttpRequest;
@@ -15,12 +14,11 @@
 import jakarta.inject.Inject;
 import org.junit.jupiter.api.Test;
 
-import java.util.List;
-
-import static org.hamcrest.Matchers.*;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
 
-class MetricControllerTest extends AbstractMemoryRunnerTest {
+class MetricControllerTest extends JdbcH2ControllerTest {
     private static final String TESTS_FLOW_NS = "io.kestra.tests";
 
     @Inject
@@ -28,7 +26,7 @@ class MetricControllerTest extends AbstractMemoryRunnerTest {
     RxHttpClient client;
 
     @Inject
-    MemoryMetricRepository memoryMetricRepository;
+    AbstractJdbcMetricRepository jdbcMetricRepository;
 
     @SuppressWarnings("unchecked")
     @Test
diff --git a/webserver/src/test/java/io/kestra/webserver/controllers/MiscControllerTest.java b/webserver/src/test/java/io/kestra/webserver/controllers/MiscControllerTest.java
index 08b3c6ce78..fdd410e00c 100644
--- a/webserver/src/test/java/io/kestra/webserver/controllers/MiscControllerTest.java
+++ b/webserver/src/test/java/io/kestra/webserver/controllers/MiscControllerTest.java
@@ -1,24 +1,17 @@
 package io.kestra.webserver.controllers;
 
-import io.kestra.core.models.Setting;
 import io.kestra.core.models.collectors.ExecutionUsage;
-import io.kestra.core.repositories.SettingRepositoryInterface;
-import io.kestra.core.runners.AbstractMemoryRunnerTest;
+import io.kestra.webserver.controllers.h2.JdbcH2ControllerTest;
 import io.micronaut.http.client.annotation.Client;
 import io.micronaut.rxjava2.http.client.RxHttpClient;
-import io.micronaut.test.annotation.MockBean;
 import jakarta.inject.Inject;
 import org.junit.jupiter.api.Test;
 
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import javax.validation.ConstraintViolationException;
-
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.*;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
 
-class MiscControllerTest extends AbstractMemoryRunnerTest {
+class MiscControllerTest extends JdbcH2ControllerTest {
     @Inject
     @Client("/")
     RxHttpClient client;
@@ -47,29 +40,4 @@ void executionUsage() {
         assertThat(response, notNullValue());
         // the memory executor didn't support daily statistics so we cannot have real execution usage
     }
-
-    @MockBean
-    SettingRepositoryInterface settingRepository() {
-        return new SettingRepositoryInterface() {
-            @Override
-            public Optional<Setting> findByKey(String key) {
-                return Optional.empty();
-            }
-
-            @Override
-            public List<Setting> findAll() {
-                return Collections.emptyList();
-            }
-
-            @Override
-            public Setting save(Setting setting) throws ConstraintViolationException {
-                return setting;
-            }
-
-            @Override
-            public Setting delete(Setting setting) {
-                return setting;
-            }
-        };
-    }
 }
\ No newline at end of file
diff --git a/webserver/src/test/java/io/kestra/webserver/controllers/TemplateControllerTest.java b/webserver/src/test/java/io/kestra/webserver/controllers/TemplateControllerTest.java
index e7c5252f1b..825064bf8e 100644
--- a/webserver/src/test/java/io/kestra/webserver/controllers/TemplateControllerTest.java
+++ b/webserver/src/test/java/io/kestra/webserver/controllers/TemplateControllerTest.java
@@ -2,11 +2,11 @@
 
 import io.kestra.core.models.tasks.Task;
 import io.kestra.core.models.templates.Template;
-import io.kestra.core.runners.AbstractMemoryRunnerTest;
 import io.kestra.core.tasks.debugs.Return;
 import io.kestra.core.utils.IdUtils;
-import io.kestra.repository.memory.MemoryTemplateRepository;
+import io.kestra.jdbc.repository.AbstractJdbcTemplateRepository;
 import io.kestra.webserver.controllers.domain.IdWithNamespace;
+import io.kestra.webserver.controllers.h2.JdbcH2ControllerTest;
 import io.kestra.webserver.responses.BulkResponse;
 import io.kestra.webserver.responses.PagedResults;
 import io.micronaut.core.type.Argument;
@@ -36,20 +36,20 @@
 import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
-class TemplateControllerTest extends AbstractMemoryRunnerTest {
+class TemplateControllerTest extends JdbcH2ControllerTest {
     @Inject
     @Client("/")
     RxHttpClient client;
 
     @Inject
-    MemoryTemplateRepository templateRepository;
+    AbstractJdbcTemplateRepository templateRepository;
 
     @BeforeEach
     protected void init() throws IOException, URISyntaxException {
         templateRepository.findAll()
             .forEach(templateRepository::delete);
 
-        super.init();
+        super.setup();
     }
 
     private Template createTemplate() {
diff --git a/webserver/src/test/java/io/kestra/webserver/controllers/h2/JdbcH2ControllerTest.java b/webserver/src/test/java/io/kestra/webserver/controllers/h2/JdbcH2ControllerTest.java
new file mode 100644
index 0000000000..76fc421e8f
--- /dev/null
+++ b/webserver/src/test/java/io/kestra/webserver/controllers/h2/JdbcH2ControllerTest.java
@@ -0,0 +1,40 @@
+package io.kestra.webserver.controllers.h2;
+
+
+import io.kestra.core.repositories.LocalFlowRepositoryLoader;
+import io.kestra.core.runners.RunnerUtils;
+import io.kestra.core.runners.StandAloneRunner;
+import io.kestra.core.utils.TestsUtils;
+import io.kestra.jdbc.JdbcTestUtils;
+import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
+import jakarta.inject.Inject;
+import lombok.SneakyThrows;
+import org.junit.jupiter.api.BeforeEach;
+
+@MicronautTest(transactional = false)
+public class JdbcH2ControllerTest {
+    @Inject
+    private StandAloneRunner runner;
+
+    @Inject
+    private JdbcTestUtils jdbcTestUtils;
+
+    @Inject
+    protected RunnerUtils runnerUtils;
+
+    @Inject
+    protected LocalFlowRepositoryLoader repositoryLoader;
+
+    @SneakyThrows
+    @BeforeEach
+    protected void setup() {
+        jdbcTestUtils.drop();
+        jdbcTestUtils.migrate();
+
+        TestsUtils.loads(repositoryLoader);
+
+        if (!runner.isRunning()) {
+            runner.run();
+        }
+    }
+}
diff --git a/webserver/src/test/java/io/kestra/webserver/filter/AuthenticationFilterTest.java b/webserver/src/test/java/io/kestra/webserver/filter/AuthenticationFilterTest.java
index f8b29163e9..6210f6c96e 100644
--- a/webserver/src/test/java/io/kestra/webserver/filter/AuthenticationFilterTest.java
+++ b/webserver/src/test/java/io/kestra/webserver/filter/AuthenticationFilterTest.java
@@ -2,7 +2,7 @@
 
 import io.kestra.core.models.Setting;
 import io.kestra.core.repositories.SettingRepositoryInterface;
-import io.kestra.core.runners.AbstractMemoryRunnerTest;
+import io.kestra.webserver.controllers.h2.JdbcH2ControllerTest;
 import io.micronaut.context.annotation.Property;
 import io.micronaut.context.annotation.Value;
 import io.micronaut.http.HttpRequest;
@@ -14,17 +14,17 @@
 import jakarta.inject.Inject;
 import org.junit.jupiter.api.Test;
 
+import javax.validation.ConstraintViolationException;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
-import javax.validation.ConstraintViolationException;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
 @Property(name = "kestra.server.basic-auth.enabled", value = "true")
-class AuthenticationFilterTest extends AbstractMemoryRunnerTest {
+class AuthenticationFilterTest extends JdbcH2ControllerTest {
     @Inject
     @Client("/")
     private RxHttpClient client;
@@ -64,29 +64,4 @@ void testAuthenticated() {
 
         assertThat(response.getStatus(), is(HttpStatus.OK));
     }
-
-    @MockBean
-    SettingRepositoryInterface settingRepository() {
-        return new SettingRepositoryInterface() {
-            @Override
-            public Optional<Setting> findByKey(String key) {
-                return Optional.empty();
-            }
-
-            @Override
-            public List<Setting> findAll() {
-                return Collections.emptyList();
-            }
-
-            @Override
-            public Setting save(Setting setting) throws ConstraintViolationException {
-                return setting;
-            }
-
-            @Override
-            public Setting delete(Setting setting) {
-                return setting;
-            }
-        };
-    }
 }
\ No newline at end of file
diff --git a/webserver/src/test/resources/application.yml b/webserver/src/test/resources/application.yml
index b18ae33884..2dc1c5dd5d 100644
--- a/webserver/src/test/resources/application.yml
+++ b/webserver/src/test/resources/application.yml
@@ -11,10 +11,6 @@ micronaut:
         url: http://localhost:8081
 
 kestra:
-  repository:
-    type: memory
-  queue:
-    type: memory
   storage:
     type: local
     local:
@@ -34,3 +30,59 @@ kestra:
       open-urls:
         - "/ping"
         - "/api/v1/executions/webhook/"
+  queue:
+    type: h2
+  repository:
+    type: h2
+  jdbc:
+    tables:
+      queues:
+        table: "queues"
+      flows:
+        table: "flows"
+        cls: io.kestra.core.models.flows.Flow
+      executions:
+        table: "executions"
+        cls: io.kestra.core.models.executions.Execution
+      templates:
+        table: "templates"
+        cls: io.kestra.core.models.templates.Template
+      triggers:
+        table: "triggers"
+        cls: io.kestra.core.models.triggers.Trigger
+      logs:
+        table: "logs"
+        cls: io.kestra.core.models.executions.LogEntry
+      metrics:
+        table: "metrics"
+        cls: io.kestra.core.models.executions.MetricEntry
+      multipleconditions:
+        table: "multipleconditions"
+        cls: io.kestra.core.models.triggers.multipleflows.MultipleConditionWindow
+      workertaskexecutions:
+        table: "workertaskexecutions"
+        cls: io.kestra.core.runners.WorkerTaskExecution
+      executorstate:
+        table: "executorstate"
+        cls: io.kestra.core.runners.ExecutorState
+      executordelayed:
+        table: "executordelayed"
+        cls: io.kestra.core.runners.ExecutionDelay
+      settings:
+        table: "settings"
+        cls: io.kestra.core.models.Setting
+      flowtopologies:
+        table: "flow_topologies"
+        cls: io.kestra.core.models.topologies.FlowTopology
+datasources:
+  h2:
+    url: jdbc:h2:mem:public;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+    username: sa
+    password: ""
+    driverClassName: org.h2.Driver
+flyway:
+  datasources:
+    h2:
+      enabled: true
+      locations:
+        - classpath:migrations/h2
\ No newline at end of file