content: /*
   * Copyright 2017-2025 Hyland Software, Inc. and its affiliates.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.activiti.cloud.services.query.rest;
  
  import static io.restassured.module.mockmvc.RestAssuredMockMvc.given;
  import static io.restassured.module.mockmvc.RestAssuredMockMvc.postProcessors;
  import static io.restassured.module.mockmvc.RestAssuredMockMvc.webAppContextSetup;
  import static org.hamcrest.Matchers.contains;
  import static org.hamcrest.Matchers.containsInAnyOrder;
  import static org.hamcrest.Matchers.containsInRelativeOrder;
  import static org.hamcrest.Matchers.empty;
  import static org.hamcrest.Matchers.equalTo;
  import static org.hamcrest.Matchers.hasItem;
  import static org.hamcrest.Matchers.is;
  import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
  import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
  
  import java.math.BigDecimal;
  import java.util.Date;
  import java.util.stream.IntStream;
  import org.activiti.QueryRestTestApplication;
  import org.activiti.api.process.model.ProcessInstance;
  import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration;
  import org.activiti.cloud.services.query.app.repository.ProcessDefinitionRepository;
  import org.activiti.cloud.services.query.model.ProcessDefinitionEntity;
  import org.activiti.cloud.services.query.model.ProcessInstanceEntity;
  import org.activiti.cloud.services.query.model.ProcessVariableKey;
  import org.activiti.cloud.services.query.rest.filter.FilterOperator;
  import org.activiti.cloud.services.query.rest.filter.VariableFilter;
  import org.activiti.cloud.services.query.rest.filter.VariableType;
  import org.activiti.cloud.services.query.rest.payload.CloudRuntimeEntitySort;
  import org.activiti.cloud.services.query.rest.payload.ProcessInstanceSearchRequest;
  import org.activiti.cloud.services.query.util.ProcessInstanceSearchRequestBuilder;
  import org.activiti.cloud.services.query.util.QueryTestUtils;
  import org.junit.jupiter.api.AfterEach;
  import org.junit.jupiter.api.BeforeEach;
  import org.junit.jupiter.api.Test;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.data.domain.Sort;
  import org.springframework.http.MediaType;
  import org.springframework.test.context.ContextConfiguration;
  import org.springframework.web.context.WebApplicationContext;
  import org.testcontainers.junit.jupiter.Testcontainers;
  
  @Testcontainers
  @ContextConfiguration(classes = { QueryRestTestApplication.class, AlfrescoWebAutoConfiguration.class })
  abstract class AbstractProcessInstanceEntitySearchControllerIT {
  
      private static final String PROCESS_DEFINITION_KEY = "process-def-key";
      private static final String VAR_NAME = "var-name";
      public static final String USER = "testuser";
  
      @Autowired
      private WebApplicationContext context;
  
      @Autowired
      protected QueryTestUtils queryTestUtils;
  
      @Autowired
      private ProcessDefinitionRepository processDefinitionRepository;
  
      protected static final String PROCESS_INSTANCES_JSON_PATH = "_embedded.processInstances";
      protected static final String PROCESS_INSTANCE_IDS_JSON_PATH = "_embedded.processInstances.id";
  
      @BeforeEach
      void setUp() {
          webAppContextSetup(context);
          postProcessors(csrf().asHeader());
      }
  
      @AfterEach
      void cleanUp() {
          queryTestUtils.cleanUp();
      }
  
      protected abstract String getSearchEndpoint();
  
      protected abstract String getCountEndpoint();
  
      @Test
      public void should_excludeProcessInstances_by_processDefinitionCategoryName() throws Exception {
          // given
          ProcessDefinitionEntity processDefinitionToExclude = new ProcessDefinitionEntity();
          processDefinitionToExclude.setId("proc-def-id-to-exclude");
          processDefinitionToExclude.setKey("proc-def-key-to-exclude");
          processDefinitionToExclude.setCategory("CategoryToExclude");
          processDefinitionRepository.save(processDefinitionToExclude);
  
          queryTestUtils
              .buildProcessInstance()
              .withProcessDefinitionKey(processDefinitionToExclude.getKey())
              .withInitiator(USER)
              .buildAndSave();
  
          ProcessDefinitionEntity processDefinitionToKeep = new ProcessDefinitionEntity();
          processDefinitionToKeep.setId("proc-def-id-to-keep");
          processDefinitionToKeep.setKey("proc-def-key-to-keep");
          processDefinitionToKeep.setCategory("CategoryToKeep");
          processDefinitionRepository.save(processDefinitionToKeep);
  
          ProcessInstanceEntity processInstanceToKeep = queryTestUtils
              .buildProcessInstance()
              .withProcessDefinitionKey(processDefinitionToKeep.getKey())
              .withInitiator(USER)
              .buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withExcludeByProcessCategoryName("CategoryToExclude");
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              // then
              .then()
              .statusCode(200)
              .body("_embedded.processInstances", hasSize(1))
              .body("_embedded.processInstances[0].id", equalTo(processInstanceToKeep.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredById() {
          IntStream
              .range(0, 3)
              .forEach(i -> queryTestUtils.buildProcessInstance().withId("id" + i).withInitiator(USER).buildAndSave());
  
          ProcessInstanceSearchRequest request = new ProcessInstanceSearchRequestBuilder().withIds("id0", "id2").build();
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(request)
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, contains("id0", "id2"));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(request)
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("2"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByParentId() {
          queryTestUtils.buildProcessInstance().withId("id1").withInitiator(USER).withParentId("parent1").buildAndSave();
  
          queryTestUtils.buildProcessInstance().withId("id2").withInitiator(USER).withParentId("parent2").buildAndSave();
  
          queryTestUtils.buildProcessInstance().withId("id3").withInitiator(USER).withParentId("parent3").buildAndSave();
  
          queryTestUtils.buildProcessInstance().withId("id4").withInitiator(USER).buildAndSave();
  
          ProcessInstanceSearchRequest request = new ProcessInstanceSearchRequestBuilder()
              .withParentIds("parent1", "parent3")
              .build();
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(request)
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, contains("id1", "id3"));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(request)
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("2"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByNameLike() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withName("Beautiful process instance name")
              .buildAndSave();
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withName("Amazing process instance name")
              .buildAndSave();
          queryTestUtils.buildProcessInstance().withInitiator(USER).withName("Ugly process instance name").buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withNames("amazing", "beautiful");
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("2"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByAppVersion() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withAppVersion("1.0.0")
              .buildAndSave();
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withAppVersion("2.0.0")
              .buildAndSave();
          queryTestUtils.buildProcessInstance().withInitiator(USER).withAppVersion("3.0.0").buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withAppVersions("1.0.0", "2.0.0");
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("2"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByStatus() {
          queryTestUtils
              .buildProcessInstance()
              .withId("id1")
              .withInitiator(USER)
              .withStatus(ProcessInstance.ProcessInstanceStatus.RUNNING)
              .buildAndSave();
          queryTestUtils
              .buildProcessInstance()
              .withId("id2")
              .withInitiator(USER)
              .withStatus(ProcessInstance.ProcessInstanceStatus.COMPLETED)
              .buildAndSave();
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withStatus(ProcessInstance.ProcessInstanceStatus.SUSPENDED)
              .buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withStatus(ProcessInstance.ProcessInstanceStatus.RUNNING, ProcessInstance.ProcessInstanceStatus.COMPLETED);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem("id1"))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem("id2"));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("2"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByLastModifiedFrom() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withLastModified(new Date(2000))
              .buildAndSave();
          queryTestUtils.buildProcessInstance().withInitiator(USER).withLastModified(new Date(1000)).buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withLastModifiedFrom(new Date(1000));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByLastModifiedTo() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withLastModified(new Date(1000))
              .buildAndSave();
          queryTestUtils.buildProcessInstance().withInitiator(USER).withLastModified(new Date(2000)).buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withLastModifiedTo(new Date(2000));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByStartFrom() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withStartDate(new Date(2000))
              .buildAndSave();
          queryTestUtils.buildProcessInstance().withInitiator(USER).withStartDate(new Date(1000)).buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withStartFrom(new Date(1000));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByStartTo() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withStartDate(new Date(1000))
              .buildAndSave();
          queryTestUtils.buildProcessInstance().withInitiator(USER).withStartDate(new Date(2000)).buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withStartTo(new Date(2000));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByCompletedFrom() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withCompletedDate(new Date(2000))
              .buildAndSave();
          queryTestUtils.buildProcessInstance().withInitiator(USER).withCompletedDate(new Date(1000)).buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withCompletedFrom(new Date(1000));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByCompletedTo() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withCompletedDate(new Date(1000))
              .buildAndSave();
          queryTestUtils.buildProcessInstance().withInitiator(USER).withCompletedDate(new Date(2000)).buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withCompletedTo(new Date(2000));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredBySuspendedFrom() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withSuspendedDate(new Date(2000))
              .buildAndSave();
          queryTestUtils.buildProcessInstance().withInitiator(USER).withSuspendedDate(new Date(1000)).buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withSuspendedFrom(new Date(1000));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredBySuspendedTo() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withSuspendedDate(new Date(1000))
              .buildAndSave();
          queryTestUtils.buildProcessInstance().withInitiator(USER).withSuspendedDate(new Date(2000)).buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withSuspendedTo(new Date(2000));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnPaginatedProcessInstances_whenNoFilters() {
          for (int i = 0; i < 5; i++) {
              queryTestUtils
                  .buildProcessInstance()
                  .withId(String.valueOf(i))
                  .withTasks(
                      queryTestUtils
                          .buildTask()
                          .withTaskCandidateUsers(USER, "other-user")
                          .withTaskCandidateGroups("group1", "group2"),
                      queryTestUtils
                          .buildTask()
                          .withTaskCandidateUsers(USER, "other-user")
                          .withTaskCandidateGroups("group1", "group2")
                  )
                  .withInitiator(USER)
                  .buildAndSave();
          }
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder();
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(5))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, containsInAnyOrder("0", "1", "2", "3", "4"))
              .body("page.totalElements", equalTo(5));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("5"));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .param("skipCount", 0)
              .param("maxItems", 2)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body("page.totalElements", equalTo(5));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("5"));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .param("skipCount", 2)
              .param("maxItems", 2)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body("page.totalElements", equalTo(5));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("5"));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .param("skipCount", 4)
              .param("maxItems", 2)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body("page.totalElements", equalTo(5));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("5"));
      }
  
      @Test
      void should_returnProcessInstance_withoutProcessVariables() {
          ProcessInstanceEntity processInstance = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "value1"),
                  new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2")
              )
              .buildAndSave();
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body("{}")
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance.getId()))
              .body(PROCESS_INSTANCES_JSON_PATH + "[0].variables", empty());
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body("{}")
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_withJustRequestedProcessVariables() {
          ProcessInstanceEntity processInstance = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "value1"),
                  new QueryTestUtils.VariableInput("var2", VariableType.INTEGER, 1),
                  new QueryTestUtils.VariableInput("var3", VariableType.STRING, "value3"),
                  new QueryTestUtils.VariableInput("var4", VariableType.BOOLEAN, true)
              )
              .buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableKeys(
                  new ProcessVariableKey(PROCESS_DEFINITION_KEY, VAR_NAME),
                  new ProcessVariableKey(PROCESS_DEFINITION_KEY, "var3")
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance.getId()))
              .body(PROCESS_INSTANCES_JSON_PATH + "[0].variables", hasSize(2))
              .body(PROCESS_INSTANCES_JSON_PATH + "[0].variables.name", hasItem(VAR_NAME))
              .body(PROCESS_INSTANCES_JSON_PATH + "[0].variables.name", hasItem("var3"));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstance_filteredByVariable_whenAllFiltersMatch() {
          ProcessInstanceEntity processInstance = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "value1"),
                  new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2")
              )
              .buildAndSave();
  
          VariableFilter matchingFilter1 = new VariableFilter(
              processInstance.getProcessDefinitionKey(),
              VAR_NAME,
              VariableType.STRING,
              "value1",
              FilterOperator.EQUALS
          );
  
          VariableFilter matchingFilter2 = new VariableFilter(
              processInstance.getProcessDefinitionKey(),
              "var2",
              VariableType.STRING,
              "value2",
              FilterOperator.EQUALS
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(matchingFilter1, matchingFilter2);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_not_returnProcessInstance_filteredByVariable_whenOneFilterDoesNotMatch() {
          ProcessInstanceEntity processInstance = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "value1"),
                  new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2")
              )
              .buildAndSave();
  
          VariableFilter matchingFilter = new VariableFilter(
              processInstance.getProcessDefinitionKey(),
              VAR_NAME,
              VariableType.STRING,
              "value1",
              FilterOperator.EQUALS
          );
  
          VariableFilter nonMatchingFilter = new VariableFilter(
              processInstance.getProcessDefinitionKey(),
              "var2",
              VariableType.STRING,
              "value3",
              FilterOperator.EQUALS
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(matchingFilter, nonMatchingFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body("page.totalElements", equalTo(0));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("0"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByStringVariable_exactMatch() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "value1"))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "other-value"))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.STRING,
              "value1",
              FilterOperator.EQUALS
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByStringVariable_notEquals() {
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "value1"))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "other-value"))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.STRING,
              "value1",
              FilterOperator.NOT_EQUALS
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByStringVariable_Contains() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "abcdefg"))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "other-value"))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.STRING,
              "bcde",
              FilterOperator.LIKE
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByIntegerVariable_equals() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 1))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 2))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.INTEGER,
              String.valueOf(1),
              FilterOperator.EQUALS
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnTaskInstances_filteredByIntegerVariable_notEquals() {
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 1))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 2))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.INTEGER,
              String.valueOf(1),
              FilterOperator.NOT_EQUALS
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByIntegerVariable_greaterThan() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 10))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 2))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.INTEGER,
              String.valueOf(2),
              FilterOperator.GREATER_THAN
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByIntegerVariable_greaterThanEqual() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 10))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 2))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.INTEGER,
              String.valueOf(2),
              FilterOperator.GREATER_THAN_OR_EQUAL
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("2"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByIntegerVariable_lessThan() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 2))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 10))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.INTEGER,
              String.valueOf(10),
              FilterOperator.LESS_THAN
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByIntegerVariable_lessThanEqual() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 2))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 10))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.INTEGER,
              String.valueOf(10),
              FilterOperator.LESS_THAN_OR_EQUAL
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("2"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByIntegerVariable_range() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 4))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 8))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance3 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 15))
              .buildAndSave();
  
          VariableFilter filterGt = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.INTEGER,
              "4",
              FilterOperator.GREATER_THAN
          );
  
          VariableFilter filterLt = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.INTEGER,
              "15",
              FilterOperator.LESS_THAN
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(filterGt, filterLt);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
  
          VariableFilter filterGtEq = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.INTEGER,
              "4",
              FilterOperator.GREATER_THAN_OR_EQUAL
          );
  
          VariableFilter filterLtEq = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.INTEGER,
              "15",
              FilterOperator.LESS_THAN_OR_EQUAL
          );
  
          requestBuilder = new ProcessInstanceSearchRequestBuilder().withProcessVariableFilters(filterGtEq, filterLtEq);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance3.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByBigDecimalVariable_equals() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("1.112")))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("1.11")))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.BIGDECIMAL,
              "1.112",
              FilterOperator.EQUALS
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByBigDecimalVariable_notEquals() {
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("1.1")))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("1.2")))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.BIGDECIMAL,
              "1.1",
              FilterOperator.NOT_EQUALS
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body("page.totalElements", equalTo(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByBigDecimalVariable_greaterThan() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("10.1")))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("2.1")))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.BIGDECIMAL,
              "2.1",
              FilterOperator.GREATER_THAN
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByBigDecimalVariable_greaterThanEqual() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("10.1")))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("2.1")))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.BIGDECIMAL,
              "2.1",
              FilterOperator.GREATER_THAN_OR_EQUAL
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("2"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByBigDecimalVariable_lessThan() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("2.1")))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("10.1")))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.BIGDECIMAL,
              "10.1",
              FilterOperator.LESS_THAN
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByBigDecimalVariable_lessThanEqual() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("2.1")))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("10.1")))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.BIGDECIMAL,
              "10.1",
              FilterOperator.LESS_THAN_OR_EQUAL
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("2"));
      }
  
      @Test
      void should_returnProcessInstances_filteredBigdecimalVariable_range() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("4.8")))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("15.16")))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance3 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("23.42")))
              .buildAndSave();
  
          VariableFilter filterGt = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.BIGDECIMAL,
              "4.8",
              FilterOperator.GREATER_THAN
          );
  
          VariableFilter filterLt = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.BIGDECIMAL,
              "23.42",
              FilterOperator.LESS_THAN
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(filterGt, filterLt);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
  
          VariableFilter filterGtEq = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.BIGDECIMAL,
              "4.8",
              FilterOperator.GREATER_THAN_OR_EQUAL
          );
  
          VariableFilter filterLtEq = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.BIGDECIMAL,
              "23.42",
              FilterOperator.LESS_THAN_OR_EQUAL
          );
  
          requestBuilder = new ProcessInstanceSearchRequestBuilder().withProcessVariableFilters(filterGtEq, filterLtEq);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance3.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDateVariable_equals() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-01"))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-02"))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATE,
              "2024-09-01",
              FilterOperator.EQUALS
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDateVariable_notEquals() {
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-01"))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-02"))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATE,
              "2024-09-01",
              FilterOperator.NOT_EQUALS
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDateVariable_greaterThan() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-02"))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-01"))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATE,
              "2024-09-01",
              FilterOperator.GREATER_THAN
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDateVariable_greaterThanEqual() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-02"))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-01"))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATE,
              "2024-09-01",
              FilterOperator.GREATER_THAN_OR_EQUAL
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("2"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDateVariable_lessThan() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-01"))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-02"))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATE,
              "2024-09-02",
              FilterOperator.LESS_THAN
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDateVariable_lessThanEquals() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-01"))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-02"))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATE,
              "2024-09-02",
              FilterOperator.LESS_THAN_OR_EQUAL
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("2"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDateVariable_range() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-01"))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-02"))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance3 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-03"))
              .buildAndSave();
  
          VariableFilter filterGt = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATE,
              "2024-09-01",
              FilterOperator.GREATER_THAN
          );
  
          VariableFilter filterLt = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATE,
              "2024-09-03",
              FilterOperator.LESS_THAN
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(filterGt, filterLt);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
  
          VariableFilter filterGtEq = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATE,
              "2024-09-01",
              FilterOperator.GREATER_THAN_OR_EQUAL
          );
  
          VariableFilter filterLtEq = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATE,
              "2024-09-03",
              FilterOperator.LESS_THAN_OR_EQUAL
          );
  
          requestBuilder = new ProcessInstanceSearchRequestBuilder().withProcessVariableFilters(filterGtEq, filterLtEq);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance3.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDatetimeVariable_equals() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00")
              )
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00")
              )
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATETIME,
              "2024-09-01T00:11:00.000+00:00",
              FilterOperator.EQUALS
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDatetimeVariable_notEquals() {
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00")
              )
              .buildAndSave();
  
          ProcessInstanceEntity processInstance = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00")
              )
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATETIME,
              "2024-09-01T00:11:00.000+00:00",
              FilterOperator.NOT_EQUALS
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDatetimeVariable_greaterThan() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00")
              )
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00")
              )
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATETIME,
              "2024-09-01T00:11:00.000+00:00",
              FilterOperator.GREATER_THAN
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDatetimeVariable_greaterThanEqual() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00")
              )
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00")
              )
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATETIME,
              "2024-09-01T00:11:00.000+00:00",
              FilterOperator.GREATER_THAN_OR_EQUAL
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("2"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDatetimeVariable_lessThan() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00")
              )
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00")
              )
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATETIME,
              "2024-09-01T00:12:00.000+00:00",
              FilterOperator.LESS_THAN
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDatetimeVariable_lessThanEqual() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00")
              )
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00")
              )
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATETIME,
              "2024-09-01T00:12:00.000+00:00",
              FilterOperator.LESS_THAN_OR_EQUAL
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("2"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByDatetimeVariable_range() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00")
              )
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00")
              )
              .buildAndSave();
  
          ProcessInstanceEntity processInstance3 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:13:00.000+00:00")
              )
              .buildAndSave();
  
          VariableFilter filterGt = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATETIME,
              "2024-09-01T00:11:00.000+00:00",
              FilterOperator.GREATER_THAN
          );
  
          VariableFilter filterLt = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATETIME,
              "2024-09-01T00:13:00.000+00:00",
              FilterOperator.LESS_THAN
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(filterGt, filterLt);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
  
          VariableFilter filterGtEq = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATETIME,
              "2024-09-01T00:11:00.000+00:00",
              FilterOperator.GREATER_THAN_OR_EQUAL
          );
  
          VariableFilter filterLtEq = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.DATETIME,
              "2024-09-01T00:13:00.000+00:00",
              FilterOperator.LESS_THAN_OR_EQUAL
          );
  
          requestBuilder = new ProcessInstanceSearchRequestBuilder().withProcessVariableFilters(filterGtEq, filterLtEq);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance2.getId()))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance3.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
      }
  
      @Test
      void should_returnProcessInstances_filteredByBooleanVariable() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BOOLEAN, true))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BOOLEAN, false))
              .buildAndSave();
  
          VariableFilter variableFilter = new VariableFilter(
              PROCESS_DEFINITION_KEY,
              VAR_NAME,
              VariableType.BOOLEAN,
              "true",
              FilterOperator.EQUALS
          );
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(variableFilter);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(1))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, hasItem(processInstance1.getId()));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("1"));
      }
  
      @Test
      void should_returnProcessInstances_sortedBy_RootFields() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withName("Nice name")
              .withInitiator(USER)
              .withStartDate(new Date(3000))
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withName("Good name")
              .withInitiator(USER)
              .withStartDate(new Date(2000))
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .buildAndSave();
  
          ProcessInstanceEntity processInstance3 = queryTestUtils
              .buildProcessInstance()
              .withName("Amazing name")
              .withInitiator(USER)
              .withStartDate(new Date(4000))
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withSort(new CloudRuntimeEntitySort("name", Sort.Direction.ASC, false, null, null));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  contains(processInstance3.getId(), processInstance2.getId(), processInstance1.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
  
          requestBuilder =
              new ProcessInstanceSearchRequestBuilder()
                  .withSort(new CloudRuntimeEntitySort("startDate", Sort.Direction.DESC, false, null, null));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  contains(processInstance3.getId(), processInstance1.getId(), processInstance2.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
      }
  
      @Test
      void should_returnProcessInstances_sortedBy_StringProcessVariable() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "cool"))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "amazing"))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance3 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "beautiful"))
              .buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withSort(
                  new CloudRuntimeEntitySort(
                      VAR_NAME,
                      Sort.Direction.ASC,
                      true,
                      PROCESS_DEFINITION_KEY,
                      VariableType.STRING
                  )
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  contains(processInstance2.getId(), processInstance3.getId(), processInstance1.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
  
          requestBuilder =
              new ProcessInstanceSearchRequestBuilder()
                  .withSort(
                      new CloudRuntimeEntitySort(
                          VAR_NAME,
                          Sort.Direction.DESC,
                          true,
                          PROCESS_DEFINITION_KEY,
                          VariableType.STRING
                      )
                  );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  contains(processInstance1.getId(), processInstance3.getId(), processInstance2.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
      }
  
      @Test
      void should_returnProcessInstances_sortedBy_IntegerProcessVariable() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 2))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 3))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance3 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.INTEGER, 1))
              .buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withSort(
                  new CloudRuntimeEntitySort(
                      VAR_NAME,
                      Sort.Direction.ASC,
                      true,
                      PROCESS_DEFINITION_KEY,
                      VariableType.INTEGER
                  )
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  contains(processInstance3.getId(), processInstance1.getId(), processInstance2.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
  
          requestBuilder =
              new ProcessInstanceSearchRequestBuilder()
                  .withSort(
                      new CloudRuntimeEntitySort(
                          VAR_NAME,
                          Sort.Direction.DESC,
                          true,
                          PROCESS_DEFINITION_KEY,
                          VariableType.INTEGER
                      )
                  );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  contains(processInstance2.getId(), processInstance1.getId(), processInstance3.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
      }
  
      @Test
      void should_returnProcessInstances_sortedBy_BigdecimalProcessVariable() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("2.1")))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("10.1")))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance3 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BIGDECIMAL, new BigDecimal("5.1")))
              .buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withSort(
                  new CloudRuntimeEntitySort(
                      VAR_NAME,
                      Sort.Direction.ASC,
                      true,
                      PROCESS_DEFINITION_KEY,
                      VariableType.BIGDECIMAL
                  )
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  contains(processInstance1.getId(), processInstance3.getId(), processInstance2.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
  
          requestBuilder =
              new ProcessInstanceSearchRequestBuilder()
                  .withSort(
                      new CloudRuntimeEntitySort(
                          VAR_NAME,
                          Sort.Direction.DESC,
                          true,
                          PROCESS_DEFINITION_KEY,
                          VariableType.BIGDECIMAL
                      )
                  );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  contains(processInstance2.getId(), processInstance3.getId(), processInstance1.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
      }
  
      @Test
      void should_returnProcessInstances_sortedBy_DateProcessVariable() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-03"))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-01"))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance3 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATE, "2024-09-02"))
              .buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withSort(
                  new CloudRuntimeEntitySort(
                      VAR_NAME,
                      Sort.Direction.ASC,
                      true,
                      PROCESS_DEFINITION_KEY,
                      VariableType.DATE
                  )
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  contains(processInstance2.getId(), processInstance3.getId(), processInstance1.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
  
          requestBuilder =
              new ProcessInstanceSearchRequestBuilder()
                  .withSort(
                      new CloudRuntimeEntitySort(
                          VAR_NAME,
                          Sort.Direction.DESC,
                          true,
                          PROCESS_DEFINITION_KEY,
                          VariableType.DATE
                      )
                  );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  contains(processInstance1.getId(), processInstance3.getId(), processInstance2.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
      }
  
      @Test
      void should_returnProcessInstances_sortedBy_DatetimeProcessVariable() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00")
              )
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:10:00.000+00:00")
              )
              .buildAndSave();
  
          ProcessInstanceEntity processInstance3 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(
                  new QueryTestUtils.VariableInput(VAR_NAME, VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00")
              )
              .buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withSort(
                  new CloudRuntimeEntitySort(
                      VAR_NAME,
                      Sort.Direction.ASC,
                      true,
                      PROCESS_DEFINITION_KEY,
                      VariableType.DATETIME
                  )
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  contains(processInstance2.getId(), processInstance1.getId(), processInstance3.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
  
          requestBuilder =
              new ProcessInstanceSearchRequestBuilder()
                  .withSort(
                      new CloudRuntimeEntitySort(
                          VAR_NAME,
                          Sort.Direction.DESC,
                          true,
                          PROCESS_DEFINITION_KEY,
                          VariableType.DATETIME
                      )
                  );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  contains(processInstance3.getId(), processInstance1.getId(), processInstance2.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
      }
  
      @Test
      void should_returnProcessInstances_sortedBy_BooleanProcessVariable() {
          ProcessInstanceEntity processInstance1 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BOOLEAN, true))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance2 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BOOLEAN, false))
              .buildAndSave();
  
          ProcessInstanceEntity processInstance3 = queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.BOOLEAN, true))
              .buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withSort(
                  new CloudRuntimeEntitySort(
                      VAR_NAME,
                      Sort.Direction.ASC,
                      true,
                      PROCESS_DEFINITION_KEY,
                      VariableType.BOOLEAN
                  )
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  containsInRelativeOrder(processInstance2.getId(), processInstance1.getId())
              )
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  containsInRelativeOrder(processInstance2.getId(), processInstance3.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
  
          requestBuilder =
              new ProcessInstanceSearchRequestBuilder()
                  .withSort(
                      new CloudRuntimeEntitySort(
                          VAR_NAME,
                          Sort.Direction.DESC,
                          true,
                          PROCESS_DEFINITION_KEY,
                          VariableType.BOOLEAN
                      )
                  );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(3))
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  containsInRelativeOrder(processInstance1.getId(), processInstance2.getId())
              )
              .body(
                  PROCESS_INSTANCE_IDS_JSON_PATH,
                  containsInRelativeOrder(processInstance3.getId(), processInstance2.getId())
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("3"));
      }
  
      /**
       * From Postgres documentation: <a href="https://www.postgresql.org/docs/current/queries-order.html">Postgres sorting</a>
       *  By default, null values sort as if larger than any non-null value;
       *  that is, NULLS FIRST is the default for DESC order, and NULLS LAST otherwise.
       *  We are overriding this behavior in order to have null values always at the end
       *  by setting property hibernate.order_by.default_null_ordering=last in CustomHibernateAutoConfiguration
       */
      @Test
      void should_returnProcessInstances_paginatedAndSortedByProcessVariables_respectingNullsLastBehaviour() {
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "cool"))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "amazing"))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "best"))
              .buildAndSave();
  
          queryTestUtils
              .buildProcessInstance()
              .withInitiator(USER)
              .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
              .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, null))
              .buildAndSave();
  
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableKeys(new ProcessVariableKey(PROCESS_DEFINITION_KEY, VAR_NAME))
              .withSort(
                  new CloudRuntimeEntitySort(
                      VAR_NAME,
                      Sort.Direction.ASC,
                      true,
                      PROCESS_DEFINITION_KEY,
                      VariableType.STRING
                  )
              );
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .param("skipCount", 0)
              .param("maxItems", 4)
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(4))
              .body(
                  "_embedded.processInstances.collect { it.variables[0].value }",
                  contains("amazing", "best", "cool", null)
              )
              .body("page.totalElements", is(4));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("4"));
  
          requestBuilder.invertSort();
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .param("skipCount", 0)
              .param("maxItems", 4)
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(4))
              .body(
                  "_embedded.processInstances.collect { it.variables[0].value }",
                  contains("cool", "best", "amazing", null)
              )
              .body("page.totalElements", is(4));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("4"));
      }
  
      @Test
      void should_returnBadRequest_when_sortParameterIsInvalid() {
          ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withSort(new CloudRuntimeEntitySort(VAR_NAME, Sort.Direction.ASC, true, null, VariableType.STRING));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(400);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("0"));
  
          requestBuilder =
              new ProcessInstanceSearchRequestBuilder()
                  .withSort(new CloudRuntimeEntitySort(VAR_NAME, Sort.Direction.ASC, true, PROCESS_DEFINITION_KEY, null));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(400);
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(requestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("0"));
      }
  
      @Test
      void should_returnFilteredPaginatedAndSortedProcessInstances() {
          for (int i = 0; i < 10; i++) {
              queryTestUtils
                  .buildProcessInstance()
                  .withId(String.valueOf(i))
                  .withInitiator(USER)
                  .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
                  .withVariables(new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "value"))
                  .buildAndSave();
          }
  
          ProcessInstanceSearchRequestBuilder taskSearchRequestBuilder = new ProcessInstanceSearchRequestBuilder()
              .withProcessVariableFilters(
                  new VariableFilter(
                      PROCESS_DEFINITION_KEY,
                      VAR_NAME,
                      VariableType.STRING,
                      "value",
                      FilterOperator.EQUALS
                  )
              )
              .withSort(new CloudRuntimeEntitySort("id", Sort.Direction.ASC, false, null, null));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(taskSearchRequestBuilder.buildJson())
              .param("maxItems", 4)
              .param("skipCount", 0)
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(4))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, contains("0", "1", "2", "3"))
              .body("page.totalElements", is(10))
              .body("page.totalPages", is(3))
              .body("page.size", is(4))
              .body("page.number", is(0));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(taskSearchRequestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("10"));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(taskSearchRequestBuilder.buildJson())
              .param("maxItems", 4)
              .param("skipCount", 4)
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(4))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, contains("4", "5", "6", "7"))
              .body("page.totalElements", is(10))
              .body("page.totalPages", is(3))
              .body("page.size", is(4))
              .body("page.number", is(1));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(taskSearchRequestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("10"));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(taskSearchRequestBuilder.buildJson())
              .param("maxItems", 4)
              .param("skipCount", 8)
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(2))
              .body(PROCESS_INSTANCE_IDS_JSON_PATH, contains("8", "9"))
              .body("page.totalElements", is(10))
              .body("page.totalPages", is(3))
              .body("page.size", is(4))
              .body("page.number", is(2));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(taskSearchRequestBuilder.buildJson())
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("10"));
      }
  
      @Test
      void should_returnCorrectNumberOfDistinctProcessInstances() {
          for (int i = 0; i < 10; i++) {
              queryTestUtils
                  .buildProcessInstance()
                  .withId(String.valueOf(i))
                  .withInitiator(USER)
                  .withProcessDefinitionKey(PROCESS_DEFINITION_KEY)
                  .withTasks(
                      queryTestUtils
                          .buildTask()
                          .withName("task1")
                          .withVariables(
                              new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "value"),
                              new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2")
                          ),
                      queryTestUtils
                          .buildTask()
                          .withName("task2")
                          .withVariables(
                              new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "value"),
                              new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2")
                          )
                  )
                  .withVariables(
                      new QueryTestUtils.VariableInput(VAR_NAME, VariableType.STRING, "value"),
                      new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2"),
                      new QueryTestUtils.VariableInput("var3", VariableType.STRING, "value3")
                  )
                  .buildAndSave();
          }
  
          ProcessInstanceSearchRequest request = new ProcessInstanceSearchRequestBuilder().withInitiators(USER).build();
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(request)
              .param("maxItems", 10)
              .when()
              .post(getSearchEndpoint())
              .then()
              .statusCode(200)
              .body(PROCESS_INSTANCES_JSON_PATH, hasSize(10));
  
          given()
              .contentType(MediaType.APPLICATION_JSON)
              .body(request)
              .when()
              .post(getCountEndpoint())
              .then()
              .statusCode(200)
              .body(equalTo("10"));
      }
  }
  