diff --git a/src/main/java/de/numcodex/feasibility_gui_backend/query/v5/FeasibilityQueryHandlerRestController.java b/src/main/java/de/numcodex/feasibility_gui_backend/query/v5/FeasibilityQueryHandlerRestController.java index 90dbbaba..1d3e4f27 100644 --- a/src/main/java/de/numcodex/feasibility_gui_backend/query/v5/FeasibilityQueryHandlerRestController.java +++ b/src/main/java/de/numcodex/feasibility_gui_backend/query/v5/FeasibilityQueryHandlerRestController.java @@ -168,7 +168,7 @@ private URI buildResultLocationUri(HttpServletRequest httpServletRequest, : ServletUriComponentsBuilder.fromRequestUri(httpServletRequest); return uriBuilder.replacePath("") - .pathSegment("api", "v5", "query", String.valueOf(queryId)) + .pathSegment("api", "v5", "query", "feasibility", String.valueOf(queryId)) .build() .toUri(); } diff --git a/src/test/java/de/numcodex/feasibility_gui_backend/query/v5/DataqueryHandlerRestControllerIT.java b/src/test/java/de/numcodex/feasibility_gui_backend/query/v5/DataqueryHandlerRestControllerIT.java index 20237cd6..d3b1d12b 100644 --- a/src/test/java/de/numcodex/feasibility_gui_backend/query/v5/DataqueryHandlerRestControllerIT.java +++ b/src/test/java/de/numcodex/feasibility_gui_backend/query/v5/DataqueryHandlerRestControllerIT.java @@ -10,10 +10,12 @@ import de.numcodex.feasibility_gui_backend.common.api.TermCode; import de.numcodex.feasibility_gui_backend.query.QueryHandlerService; import de.numcodex.feasibility_gui_backend.query.api.status.FeasibilityIssue; +import de.numcodex.feasibility_gui_backend.query.api.status.SavedQuerySlots; import de.numcodex.feasibility_gui_backend.query.api.status.ValidationIssue; import de.numcodex.feasibility_gui_backend.query.api.validation.StructuredQueryValidatorSpringConfig; import de.numcodex.feasibility_gui_backend.query.dataquery.DataqueryException; import de.numcodex.feasibility_gui_backend.query.dataquery.DataqueryHandler; +import de.numcodex.feasibility_gui_backend.query.dataquery.DataqueryStorageFullException; import de.numcodex.feasibility_gui_backend.query.dispatch.QueryDispatchException; import de.numcodex.feasibility_gui_backend.query.persistence.UserBlacklist; import de.numcodex.feasibility_gui_backend.query.persistence.UserBlacklistRepository; @@ -90,13 +92,16 @@ public class DataqueryHandlerRestControllerIT { public void testStoreDataquery_succeedsWith201() throws Exception { long queryId = 1L; doReturn(queryId).when(dataqueryHandler).storeDataquery(any(Dataquery.class), any(String.class)); + doReturn(createSavedQuerySlots()).when(dataqueryHandler).getDataquerySlotsJson(any(String.class)); mockMvc.perform(post(URI.create(PATH_API + PATH_QUERY + PATH_DATA)).with(csrf()) .contentType(APPLICATION_JSON) .content(jsonUtil.writeValueAsString(createValidDataqueryToStore(queryId)))) .andExpect(status().isCreated()) .andExpect(header().exists("location")) - .andExpect(header().string("location", PATH_API + PATH_QUERY + PATH_DATA + "/" + queryId)); + .andExpect(header().string("location", PATH_API + PATH_QUERY + PATH_DATA + "/" + queryId)) + .andExpect(jsonPath("$.used").exists()) + .andExpect(jsonPath("$.total").exists()); } @Test @@ -110,6 +115,17 @@ public void testStoreDataqueryExceptionWith500() throws Exception { .andExpect(status().isInternalServerError()); } + @Test + @WithMockUser(roles = "DATAPORTAL_TEST_USER") + public void testStoreDataqueryExceptionWith403() throws Exception { + doThrow(DataqueryStorageFullException.class).when(dataqueryHandler).storeDataquery(any(Dataquery.class), any(String.class)); + + mockMvc.perform(post(URI.create(PATH_API + PATH_QUERY + PATH_DATA)).with(csrf()) + .contentType(APPLICATION_JSON) + .content(jsonUtil.writeValueAsString(createValidDataqueryToStore(1L)))) + .andExpect(status().isForbidden()); + } + // @Test // @WithMockUser(roles = "DATAPORTAL_TEST_USER") // public void testStoreDataquery_failsOnDuplicateWith409() throws Exception { @@ -157,6 +173,42 @@ public void testGetDataquery_failsOnJsonError() throws Exception { .andExpect(status().isInternalServerError()); } + @Test + @WithMockUser(roles = "DATAPORTAL_TEST_USER") + public void testGetDataqueryCrtdl_succeeds() throws Exception { + long dataqueryId = 1L; + var annotatedQuery = createValidAnnotatedStructuredQuery(false); + + doReturn(createValidApiDataqueryToGet(dataqueryId)).when(dataqueryHandler).getDataqueryById(any(Long.class), any(String.class)); + doReturn(annotatedQuery).when(structuredQueryValidation).annotateStructuredQuery(any(StructuredQuery.class), any(Boolean.class)); + + mockMvc.perform(get(URI.create(PATH_API + PATH_QUERY + PATH_DATA + "/" + dataqueryId + "/crtdl")).with(csrf())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.cohortDefinition.display").value(annotatedQuery.display())); + } + + @Test + @WithMockUser(roles = "DATAPORTAL_TEST_USER") + public void testGetDataqueryCrtdl_failsOnNotFound() throws Exception { + long dataqueryId = 1; + + doThrow(DataqueryException.class).when(dataqueryHandler).getDataqueryById(any(Long.class), any(String.class)); + + mockMvc.perform(get(URI.create(PATH_API + PATH_QUERY + PATH_DATA + "/" + dataqueryId + "/crtdl")).with(csrf())) + .andExpect(status().isNotFound()); + } + + @Test + @WithMockUser(roles = "DATAPORTAL_TEST_USER") + public void testGetDataqueryCrtdl_failsOnJsonError() throws Exception { + long dataqueryId = 1; + + doThrow(JsonProcessingException.class).when(dataqueryHandler).getDataqueryById(any(Long.class), any(String.class)); + + mockMvc.perform(get(URI.create(PATH_API + PATH_QUERY + PATH_DATA + "/" + dataqueryId + "/crtdl")).with(csrf())) + .andExpect(status().isInternalServerError()); + } + @Test @WithMockUser(roles = "DATAPORTAL_TEST_USER") public void testGetDataqueryList_succeeds() throws Exception { @@ -181,46 +233,81 @@ public void testGetDataqueryListByUser_succeeds() throws Exception { .andExpect(jsonPath("$.[0].id").exists()); } -// -// @Test -// @WithMockUser(roles = "DATAPORTAL_TEST_USER") -// public void testUpdateQueryTemplate_succeeds() throws Exception { -// doNothing().when(queryHandlerService).updateQueryTemplate(any(Long.class), any(Dataquery.class), any(String.class)); -// -// mockMvc.perform(put(URI.create(PATH_API + PATH_QUERY + PATH_TEMPLATE + "/1")).with(csrf()) -// .contentType(APPLICATION_JSON) -// .content(jsonUtil.writeValueAsString(createValidQueryTemplateToStore(1L)))) -// .andExpect(status().isOk()); -// } -// -// @Test -// @WithMockUser(roles = "DATAPORTAL_TEST_USER") -// public void testUpdateQueryTemplate_failsOnInvalidQueryTemplate() throws Exception { -// mockMvc.perform(put(URI.create(PATH_API + PATH_QUERY + PATH_TEMPLATE + "/1")).with(csrf()) -// .contentType(APPLICATION_JSON) -// .content("{}")) -// .andExpect(status().isBadRequest()); -// } -// -// -// @Test -// @WithMockUser(roles = "DATAPORTAL_TEST_USER") -// public void testDeleteQueryTemplate_succeeds() throws Exception { -// doNothing().when(queryHandlerService).deleteQueryTemplate(any(Long.class), any(String.class)); -// -// mockMvc.perform(delete(URI.create(PATH_API + PATH_QUERY + PATH_TEMPLATE + "/1")).with(csrf())) -// .andExpect(status().isOk()); -// } -// -// @Test -// @WithMockUser(roles = "DATAPORTAL_TEST_USER") -// public void testDeleteQueryTemplate_failsWith404OnNotFound() throws Exception { -// doThrow(QueryTemplateException.class).when(queryHandlerService).deleteQueryTemplate(any(Long.class), any(String.class)); -// -// mockMvc.perform(delete(URI.create(PATH_API + PATH_QUERY + PATH_TEMPLATE + "/1")).with(csrf())) -// .andExpect(status().isNotFound()); -// } -// + + @Test + @WithMockUser(roles = "DATAPORTAL_TEST_USER") + public void testUpdateDataquery_succeeds() throws Exception { + doNothing().when(dataqueryHandler).updateDataquery(any(Long.class), any(Dataquery.class), any(String.class)); + doReturn(createSavedQuerySlots()).when(dataqueryHandler).getDataquerySlotsJson(any(String.class)); + + mockMvc.perform(put(URI.create(PATH_API + PATH_QUERY + PATH_DATA + "/1")).with(csrf()) + .contentType(APPLICATION_JSON) + .content(jsonUtil.writeValueAsString(createValidDataqueryToStore(1L)))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.used").exists()) + .andExpect(jsonPath("$.total").exists()); + } + + @Test + @WithMockUser(roles = "DATAPORTAL_TEST_USER") + public void testUpdateDataquery_failsOnNotFound() throws Exception { + doThrow(DataqueryException.class).when(dataqueryHandler).updateDataquery(any(Long.class), any(Dataquery.class), any(String.class)); + mockMvc.perform(put(URI.create(PATH_API + PATH_QUERY + PATH_DATA + "/1")).with(csrf()) + .contentType(APPLICATION_JSON) + .content(jsonUtil.writeValueAsString(createValidDataqueryToStore(1L)))) + .andExpect(status().isNotFound()); + } + + @Test + @WithMockUser(roles = "DATAPORTAL_TEST_USER") + public void testUpdateDataquery_failsOnJsonProcessingException() throws Exception { + doThrow(JsonProcessingException.class).when(dataqueryHandler).updateDataquery(any(Long.class), any(Dataquery.class), any(String.class)); + mockMvc.perform(put(URI.create(PATH_API + PATH_QUERY + PATH_DATA + "/1")).with(csrf()) + .contentType(APPLICATION_JSON) + .content(jsonUtil.writeValueAsString(createValidDataqueryToStore(1L)))) + .andExpect(status().isUnprocessableEntity()); + } + + @Test + @WithMockUser(roles = "DATAPORTAL_TEST_USER") + public void testUpdateDataquery_failsOnStorageFull() throws Exception { + doThrow(DataqueryStorageFullException.class).when(dataqueryHandler).updateDataquery(any(Long.class), any(Dataquery.class), any(String.class)); + mockMvc.perform(put(URI.create(PATH_API + PATH_QUERY + PATH_DATA + "/1")).with(csrf()) + .contentType(APPLICATION_JSON) + .content(jsonUtil.writeValueAsString(createValidDataqueryToStore(1L)))) + .andExpect(status().isForbidden()); + } + + + @Test + @WithMockUser(roles = "DATAPORTAL_TEST_USER") + public void testDeleteDataquery_succeeds() throws Exception { + doNothing().when(dataqueryHandler).deleteDataquery(any(Long.class), any(String.class)); + + mockMvc.perform(delete(URI.create(PATH_API + PATH_QUERY + PATH_DATA + "/1")).with(csrf())) + .andExpect(status().isOk()); + } + + @Test + @WithMockUser(roles = "DATAPORTAL_TEST_USER") + public void testDeleteDataquery_failsWith404OnNotFound() throws Exception { + doThrow(DataqueryException.class).when(dataqueryHandler).deleteDataquery(any(Long.class), any(String.class)); + + mockMvc.perform(delete(URI.create(PATH_API + PATH_QUERY + PATH_DATA + "/1")).with(csrf())) + .andExpect(status().isNotFound()); + } + + @Test + @WithMockUser(roles = "DATAPORTAL_TEST_USER") + public void testGetDataquerySlots_succeeds() throws Exception { + doReturn(createSavedQuerySlots()).when(dataqueryHandler).getDataquerySlotsJson(any(String.class)); + + mockMvc.perform(delete(URI.create(PATH_API + PATH_QUERY + PATH_DATA + "/query-slots")).with(csrf())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.used").exists()) + .andExpect(jsonPath("$.total").exists()); + } + @NotNull private Dataquery createValidDataqueryToStore(long id) { return Dataquery.builder() @@ -334,4 +421,11 @@ private Criterion createInvalidCriterion() { .termCodes(List.of(createTermCode())) .build(); } + + private SavedQuerySlots createSavedQuerySlots() { + return SavedQuerySlots.builder() + .used(5) + .total(10) + .build(); + } }