diff --git a/pom.xml b/pom.xml index 2cc42f53..ca77a116 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ com.powsybl powsybl-parent-ws - 12 + 13 @@ -145,16 +145,6 @@ powsybl-config-test test - - junit - junit - test - - - org.junit.vintage - junit-vintage-engine - test - org.springframework.boot spring-boot-starter-test diff --git a/src/main/java/org/gridsuite/explore/server/RestTemplateConfig.java b/src/main/java/org/gridsuite/explore/server/RestTemplateConfig.java index 9d6d0940..4409ac0e 100644 --- a/src/main/java/org/gridsuite/explore/server/RestTemplateConfig.java +++ b/src/main/java/org/gridsuite/explore/server/RestTemplateConfig.java @@ -8,50 +8,28 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.boot.jackson.JsonComponentModule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.web.client.RestTemplate; /** * @author Etienne Homer */ @Configuration public class RestTemplateConfig { - - @Bean - public RestTemplate restTemplate() { - final RestTemplate restTemplate = new RestTemplate(); - - //find and replace Jackson message converter with our own - for (int i = 0; i < restTemplate.getMessageConverters().size(); i++) { - final HttpMessageConverter httpMessageConverter = restTemplate.getMessageConverters().get(i); - if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter) { - restTemplate.getMessageConverters().set(i, mappingJackson2HttpMessageConverter()); - } - } - - return restTemplate; - } - - public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { - MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); - converter.setObjectMapper(objectMapper()); - return converter; - } - - private ObjectMapper createObjectMapper() { - var objectMapper = Jackson2ObjectMapperBuilder.json().build(); - objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - objectMapper.registerModule(new JsonComponentModule()); - return objectMapper; - } - + /** + * we alter the {@link ObjectMapper} generated by Spring using SpringBoot system + * @return json customizer + * @see org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration JacksonAutoConfiguration + * @see org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration HttpMessageConvertersAutoConfiguration + * @see org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration RestTemplateAutoConfiguration + */ @Bean - public ObjectMapper objectMapper() { - return createObjectMapper(); + public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { + //also from .config: spring.jackson.serialization.write-dates-as-timestamps=false + return builder -> builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + //.findModulesViaServiceLoader(true) + .modulesToInstall(new JsonComponentModule()); } } diff --git a/src/main/java/org/gridsuite/explore/server/services/CaseService.java b/src/main/java/org/gridsuite/explore/server/services/CaseService.java index ab0a2963..0b04cafa 100644 --- a/src/main/java/org/gridsuite/explore/server/services/CaseService.java +++ b/src/main/java/org/gridsuite/explore/server/services/CaseService.java @@ -10,6 +10,7 @@ import org.gridsuite.explore.server.ExploreException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.*; import org.springframework.stereotype.Service; @@ -26,21 +27,16 @@ import java.util.UUID; import java.util.stream.Collectors; -import static org.gridsuite.explore.server.ExploreException.Type.*; +import static org.gridsuite.explore.server.ExploreException.Type.INCORRECT_CASE_FILE; @Service public class CaseService implements IDirectoryElementsService { - private static final String CASE_SERVER_API_VERSION = "v1"; - - private static final String DELIMITER = "/"; private final RestTemplate restTemplate; - private String caseServerBaseUri; @Autowired public CaseService(@Value("${powsybl.services.case-server.base-uri:http://case-server/}") String studyServerBaseUri, - RestTemplate restTemplate) { - this.caseServerBaseUri = studyServerBaseUri; - this.restTemplate = restTemplate; + RestTemplateBuilder restTemplateBuilder) { + this.restTemplate = restTemplateBuilder.rootUri(studyServerBaseUri + "/v1").build(); } private static ExploreException wrapRemoteError(String response, HttpStatus statusCode) { @@ -51,11 +47,7 @@ private static ExploreException wrapRemoteError(String response, HttpStatus stat } } - public void setBaseUri(String actionsServerBaseUri) { - this.caseServerBaseUri = actionsServerBaseUri; - } - - UUID importCase(MultipartFile multipartFile) { + public UUID importCase(MultipartFile multipartFile) { MultiValueMap body = new LinkedMultiValueMap<>(); UUID caseUuid; HttpHeaders headers = new HttpHeaders(); @@ -64,11 +56,9 @@ UUID importCase(MultipartFile multipartFile) { Objects.requireNonNull(multipartFile.getOriginalFilename()); body.add("file", multipartFile.getResource()); } - HttpEntity> request = new HttpEntity<>( - body, headers); + HttpEntity> request = new HttpEntity<>(body, headers); try { - caseUuid = restTemplate.postForObject(caseServerBaseUri + "/" + CASE_SERVER_API_VERSION + "/cases", request, - UUID.class); + caseUuid = restTemplate.postForObject("/cases", request, UUID.class); } catch (HttpStatusCodeException e) { if (e.getStatusCode().equals(HttpStatus.UNPROCESSABLE_ENTITY)) { throw new ExploreException(INCORRECT_CASE_FILE, e.getMessage()); @@ -78,35 +68,33 @@ UUID importCase(MultipartFile multipartFile) { return caseUuid; } - UUID duplicateCase(UUID sourceCaseUuid) { - String path = UriComponentsBuilder.fromPath(DELIMITER + CASE_SERVER_API_VERSION + "/cases") + public UUID duplicateCase(UUID sourceCaseUuid) { + String path = UriComponentsBuilder.fromPath("/cases") .queryParam("duplicateFrom", sourceCaseUuid) .toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); - return restTemplate.exchange(caseServerBaseUri + path, HttpMethod.POST, new HttpEntity<>(headers), UUID.class) + return restTemplate.exchange(path, HttpMethod.POST, new HttpEntity<>(headers), UUID.class) .getBody(); } @Override public void delete(UUID id, String userId) { - String path = UriComponentsBuilder.fromPath(DELIMITER + CASE_SERVER_API_VERSION + "/cases/{id}") + String path = UriComponentsBuilder.fromPath("/cases/{id}") .buildAndExpand(id) .toUriString(); HttpHeaders headers = new HttpHeaders(); headers.add(HEADER_USER_ID, userId); - restTemplate.exchange(caseServerBaseUri + path, HttpMethod.DELETE, new HttpEntity<>(headers), Void.class); + restTemplate.exchange(path, HttpMethod.DELETE, new HttpEntity<>(headers), Void.class); } @Override public List> getMetadata(List casesUuids) { var ids = casesUuids.stream().map(UUID::toString).collect(Collectors.joining(",")); - String path = UriComponentsBuilder - .fromPath(DELIMITER + CASE_SERVER_API_VERSION + "/cases/metadata" + "?ids=" + ids) - .buildAndExpand() + String path = UriComponentsBuilder.fromPath("/cases/metadata") + .queryParam("ids", ids) .toUriString(); - return restTemplate.exchange(caseServerBaseUri + path, HttpMethod.GET, null, - new ParameterizedTypeReference>>() { - }).getBody(); + return restTemplate.exchange(path, HttpMethod.GET, null, + new ParameterizedTypeReference>>() { }).getBody(); } } diff --git a/src/main/java/org/gridsuite/explore/server/services/ContingencyListService.java b/src/main/java/org/gridsuite/explore/server/services/ContingencyListService.java index 746ede0d..976d1670 100644 --- a/src/main/java/org/gridsuite/explore/server/services/ContingencyListService.java +++ b/src/main/java/org/gridsuite/explore/server/services/ContingencyListService.java @@ -7,8 +7,12 @@ package org.gridsuite.explore.server.services; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.*; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; @@ -23,133 +27,116 @@ */ @Service public class ContingencyListService implements IDirectoryElementsService { - private static final String ACTIONS_API_VERSION = "v1"; - private static final String DELIMITER = "/"; - private static final String HEADER_USER_ID = "userId"; private static final String HEADER_DUPLICATE_FROM = "duplicateFrom"; - private String actionsServerBaseUri; private final RestTemplate restTemplate; @Autowired - public ContingencyListService(RestTemplate restTemplate, RemoteServicesProperties remoteServicesProperties) { - this.actionsServerBaseUri = remoteServicesProperties.getServiceUri("actions-server"); - this.restTemplate = restTemplate; - } - - public void setActionsServerBaseUri(String actionsServerBaseUri) { - this.actionsServerBaseUri = actionsServerBaseUri; + public ContingencyListService(RestTemplateBuilder restTemplateBuilder, RemoteServicesProperties remoteServicesProperties) { + this.restTemplate = restTemplateBuilder.rootUri(remoteServicesProperties.getServiceUri("actions-server") + "/v1").build(); } @Override public void delete(UUID id, String userId) { - String path = UriComponentsBuilder.fromPath(DELIMITER + ACTIONS_API_VERSION + "/contingency-lists/{id}") + String path = UriComponentsBuilder.fromPath("/contingency-lists/{id}") .buildAndExpand(id) .toUriString(); HttpHeaders headers = new HttpHeaders(); headers.add(HEADER_USER_ID, userId); - restTemplate.exchange(actionsServerBaseUri + path, HttpMethod.DELETE, new HttpEntity<>(headers), Void.class); + restTemplate.exchange(path, HttpMethod.DELETE, new HttpEntity<>(headers), Void.class); } public void insertScriptContingencyList(UUID id, String content) { - String path = UriComponentsBuilder - .fromPath(DELIMITER + ACTIONS_API_VERSION + "/script-contingency-lists?id={id}") - .buildAndExpand(id) + String path = UriComponentsBuilder.fromPath("/script-contingency-lists") + .queryParam("id", id) .toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity httpEntity = new HttpEntity<>(content, headers); - restTemplate.exchange(actionsServerBaseUri + path, HttpMethod.POST, httpEntity, Void.class); + restTemplate.exchange(path, HttpMethod.POST, httpEntity, Void.class); } public void insertScriptContingencyList(UUID sourceListId, UUID id) { - String path = UriComponentsBuilder.fromPath(DELIMITER + ACTIONS_API_VERSION + "/script-contingency-lists") + String path = UriComponentsBuilder.fromPath("/script-contingency-lists") .queryParam(HEADER_DUPLICATE_FROM, sourceListId) .queryParam("id", id) .toUriString(); - restTemplate.exchange(actionsServerBaseUri + path, HttpMethod.POST, null, Void.class); + restTemplate.exchange(path, HttpMethod.POST, null, Void.class); } public void insertFormContingencyList(UUID id, String content) { - String path = UriComponentsBuilder.fromPath(DELIMITER + ACTIONS_API_VERSION + "/form-contingency-lists?id={id}") - .buildAndExpand(id) + String path = UriComponentsBuilder.fromPath("/form-contingency-lists") + .queryParam("id", id) .toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity httpEntity = new HttpEntity<>(content, headers); - restTemplate.exchange(actionsServerBaseUri + path, HttpMethod.POST, httpEntity, Void.class); + restTemplate.exchange(path, HttpMethod.POST, httpEntity, Void.class); } public void insertIdentifierContingencyList(UUID id, String content) { - String path = UriComponentsBuilder.fromPath(DELIMITER + ACTIONS_API_VERSION + "/identifier-contingency-lists?id={id}") - .buildAndExpand(id) + String path = UriComponentsBuilder.fromPath("/identifier-contingency-lists") + .queryParam("id", id) .toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity httpEntity = new HttpEntity<>(content, headers); - restTemplate.exchange(actionsServerBaseUri + path, HttpMethod.POST, httpEntity, Void.class); + restTemplate.exchange(path, HttpMethod.POST, httpEntity, Void.class); } public void insertFormContingencyList(UUID sourceListId, UUID id) { - String path = UriComponentsBuilder.fromPath(DELIMITER + ACTIONS_API_VERSION + "/form-contingency-lists") + String path = UriComponentsBuilder.fromPath("/form-contingency-lists") .queryParam(HEADER_DUPLICATE_FROM, sourceListId) .queryParam("id", id) .toUriString(); - restTemplate.exchange(actionsServerBaseUri + path, HttpMethod.POST, null, Void.class); + restTemplate.exchange(path, HttpMethod.POST, null, Void.class); } public void insertIdentifierContingencyList(UUID sourceListId, UUID id) { - String path = UriComponentsBuilder.fromPath(DELIMITER + ACTIONS_API_VERSION + "/identifier-contingency-lists") + String path = UriComponentsBuilder.fromPath("/identifier-contingency-lists") .queryParam(HEADER_DUPLICATE_FROM, sourceListId) .queryParam("id", id) .toUriString(); - restTemplate.exchange(actionsServerBaseUri + path, HttpMethod.POST, null, Void.class); + restTemplate.exchange(path, HttpMethod.POST, null, Void.class); } public void newScriptFromFormContingencyList(UUID id, UUID newId) { - String path = UriComponentsBuilder - .fromPath(DELIMITER + ACTIONS_API_VERSION + "/form-contingency-lists/{id}/new-script?newId={newId}") - .buildAndExpand(id, newId) + String path = UriComponentsBuilder.fromPath("/form-contingency-lists/{id}/new-script") + .queryParam("newId", newId) + .buildAndExpand(id) .toUriString(); - restTemplate.exchange(actionsServerBaseUri + path, HttpMethod.POST, null, Void.class); + restTemplate.exchange(path, HttpMethod.POST, null, Void.class); } public void replaceFormContingencyListWithScript(UUID id, String userId) { - String path = UriComponentsBuilder - .fromPath(DELIMITER + ACTIONS_API_VERSION + "/form-contingency-lists/{id}/replace-with-script") + String path = UriComponentsBuilder.fromPath("/form-contingency-lists/{id}/replace-with-script") .buildAndExpand(id) .toUriString(); HttpHeaders headers = new HttpHeaders(); headers.set(HEADER_USER_ID, userId); - restTemplate.exchange(actionsServerBaseUri + path, HttpMethod.POST, new HttpEntity<>(headers), Void.class); + restTemplate.exchange(path, HttpMethod.POST, new HttpEntity<>(headers), Void.class); } @Override public List> getMetadata(List contingencyListsUuids) { var ids = contingencyListsUuids.stream().map(UUID::toString).collect(Collectors.joining(",")); - String path = UriComponentsBuilder - .fromPath(DELIMITER + ACTIONS_API_VERSION + "/contingency-lists/metadata" + "?ids=" + ids) - .buildAndExpand() + String path = UriComponentsBuilder.fromPath("/contingency-lists/metadata") + .queryParam("ids", ids) .toUriString(); - return restTemplate.exchange(actionsServerBaseUri + path, HttpMethod.GET, null, - new ParameterizedTypeReference>>() { - }).getBody(); + return restTemplate.exchange(path, HttpMethod.GET, null, + new ParameterizedTypeReference>>() { }).getBody(); } public void updateContingencyList(UUID id, String content, String userId, String element) { - - String path = UriComponentsBuilder.fromPath(DELIMITER + ACTIONS_API_VERSION + element) + String path = UriComponentsBuilder.fromPath(element) .buildAndExpand(id) .toUriString(); - restTemplate.exchange(actionsServerBaseUri + path, HttpMethod.PUT, getHttpEntityWithUserHeader(userId, content), Void.class); - + restTemplate.exchange(path, HttpMethod.PUT, getHttpEntityWithUserHeader(userId, content), Void.class); } private HttpEntity getHttpEntityWithUserHeader(String userId, String content) { - HttpHeaders headers = new HttpHeaders(); headers.set(HEADER_USER_ID, userId); headers.setContentType(MediaType.APPLICATION_JSON); - return new HttpEntity<>(content, headers); } } diff --git a/src/main/java/org/gridsuite/explore/server/services/DirectoryService.java b/src/main/java/org/gridsuite/explore/server/services/DirectoryService.java index 56af9315..2785a749 100644 --- a/src/main/java/org/gridsuite/explore/server/services/DirectoryService.java +++ b/src/main/java/org/gridsuite/explore/server/services/DirectoryService.java @@ -10,6 +10,8 @@ import org.gridsuite.explore.server.dto.ElementAttributes; import org.gridsuite.explore.server.utils.ParametersType; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Lazy; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -21,9 +23,10 @@ import org.springframework.web.util.UriComponentsBuilder; import java.util.*; +import java.util.function.Predicate; import java.util.stream.Collectors; -import static org.gridsuite.explore.server.ExploreException.Type.*; +import static org.gridsuite.explore.server.ExploreException.Type.UNKNOWN_ELEMENT_TYPE; import static org.gridsuite.explore.server.services.ExploreService.*; /** @@ -31,27 +34,15 @@ */ @Service public class DirectoryService implements IDirectoryElementsService { - - private static final String DIRECTORY_SERVER_API_VERSION = "v1"; - - private static final String DELIMITER = "/"; - - private static final String DIRECTORIES_SERVER_ROOT_PATH = DELIMITER + DIRECTORY_SERVER_API_VERSION + DELIMITER - + "directories"; - - private static final String ELEMENTS_SERVER_ROOT_PATH = DELIMITER + DIRECTORY_SERVER_API_VERSION + DELIMITER - + "elements"; - private final Map genericServices; private final RestTemplate restTemplate; - private String directoryServerBaseUri; @Autowired public DirectoryService( FilterService filterService, ContingencyListService contingencyListService, StudyService studyService, - CaseService caseService, ParametersService parametersService, RestTemplate restTemplate, RemoteServicesProperties remoteServicesProperties) { - this.directoryServerBaseUri = remoteServicesProperties.getServiceUri("directory-server"); - this.restTemplate = restTemplate; + CaseService caseService, @Lazy ParametersService parametersService, RestTemplateBuilder restTemplateBuilder, + RemoteServicesProperties remoteServicesProperties) { + this.restTemplate = restTemplateBuilder.rootUri(remoteServicesProperties.getServiceUri("directory-server") + "/v1").build(); this.genericServices = Map.of( FILTER, filterService, CONTINGENCY_LIST, contingencyListService, @@ -61,89 +52,65 @@ public DirectoryService( ParametersType.VOLTAGE_INIT_PARAMETERS.name(), parametersService); } - public void setDirectoryServerBaseUri(String directoryServerBaseUri) { - this.directoryServerBaseUri = directoryServerBaseUri; - } - public ElementAttributes createElement(ElementAttributes elementAttributes, UUID directoryUuid, String userId) { - String path = UriComponentsBuilder - .fromPath(DIRECTORIES_SERVER_ROOT_PATH + "/{directoryUuid}/elements") + String path = UriComponentsBuilder.fromPath("/directories/{directoryUuid}/elements") .buildAndExpand(directoryUuid) .toUriString(); HttpHeaders headers = new HttpHeaders(); headers.add(HEADER_USER_ID, userId); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity httpEntity = new HttpEntity<>(elementAttributes, headers); - return restTemplate - .exchange(directoryServerBaseUri + path, HttpMethod.POST, httpEntity, ElementAttributes.class) - .getBody(); + return restTemplate.exchange(path, HttpMethod.POST, httpEntity, ElementAttributes.class).getBody(); } public void deleteDirectoryElement(UUID elementUuid, String userId) { - String path = UriComponentsBuilder - .fromPath(ELEMENTS_SERVER_ROOT_PATH + "/{elementUuid}") + String path = UriComponentsBuilder.fromPath("/elements/{elementUuid}") .buildAndExpand(elementUuid) .toUriString(); HttpHeaders headers = new HttpHeaders(); headers.add(HEADER_USER_ID, userId); - restTemplate.exchange(directoryServerBaseUri + path, HttpMethod.DELETE, new HttpEntity<>(headers), Void.class); + restTemplate.exchange(path, HttpMethod.DELETE, new HttpEntity<>(headers), Void.class); } public ElementAttributes getElementInfos(UUID elementUuid) { - String path = UriComponentsBuilder - .fromPath(ELEMENTS_SERVER_ROOT_PATH + "/{directoryUuid}") + String path = UriComponentsBuilder.fromPath("/elements/{directoryUuid}") .buildAndExpand(elementUuid) .toUriString(); - return restTemplate.exchange(directoryServerBaseUri + path, HttpMethod.GET, null, ElementAttributes.class) - .getBody(); + return restTemplate.exchange(path, HttpMethod.GET, null, ElementAttributes.class).getBody(); } private List getElementsInfos(List elementsUuids, List elementTypes) { var ids = elementsUuids.stream().map(UUID::toString).collect(Collectors.joining(",")); - String path = UriComponentsBuilder.fromPath(ELEMENTS_SERVER_ROOT_PATH).toUriString() + "?ids=" + ids; - - if (!CollectionUtils.isEmpty(elementTypes)) { - path += "&elementTypes=" + elementTypes.stream().collect(Collectors.joining(",")); - } - - List elementAttributesList; - elementAttributesList = restTemplate.exchange(directoryServerBaseUri + path, HttpMethod.GET, null, - new ParameterizedTypeReference>() { - }).getBody(); - if (elementAttributesList != null) { - return elementAttributesList; - } else { - return Collections.emptyList(); - } + String path = UriComponentsBuilder.fromPath("/elements") + .queryParam("ids", ids) + .queryParamIfPresent("elementTypes", Optional.ofNullable(elementTypes) + .filter(Predicate.not(List::isEmpty)).map(l -> String.join(",", l))) + .toUriString(); + List elementAttributesList = restTemplate.exchange(path, HttpMethod.GET, null, + new ParameterizedTypeReference>() { }).getBody(); + return Objects.requireNonNullElseGet(elementAttributesList, Collections::emptyList); } public void notifyDirectoryChanged(UUID elementUuid, String userId) { - String path = UriComponentsBuilder - .fromPath(ELEMENTS_SERVER_ROOT_PATH + "/{elementUuid}/notification?type={update_directory}") - .buildAndExpand(elementUuid, NotificationType.UPDATE_DIRECTORY.name()) + String path = UriComponentsBuilder.fromPath("/elements/{elementUuid}/notification") + .queryParam("type", NotificationType.UPDATE_DIRECTORY.name()) + .buildAndExpand(elementUuid) .toUriString(); - HttpHeaders headers = new HttpHeaders(); headers.add(HEADER_USER_ID, userId); - restTemplate.exchange(directoryServerBaseUri + path, HttpMethod.POST, new HttpEntity<>(headers), Void.class); + restTemplate.exchange(path, HttpMethod.POST, new HttpEntity<>(headers), Void.class); } private List getDirectoryElements(UUID directoryUuid, String userId) { - String path = UriComponentsBuilder.fromPath(DIRECTORIES_SERVER_ROOT_PATH + "/{directoryUuid}/elements") + String path = UriComponentsBuilder.fromPath("/directories/{directoryUuid}/elements") .buildAndExpand(directoryUuid) .toUriString(); HttpHeaders headers = new HttpHeaders(); headers.add(HEADER_USER_ID, userId); List elementAttributesList; - elementAttributesList = restTemplate.exchange(directoryServerBaseUri + path, HttpMethod.GET, - new HttpEntity<>(headers), new ParameterizedTypeReference>() { - }).getBody(); - - if (elementAttributesList != null) { - return elementAttributesList; - } else { - return Collections.emptyList(); - } + elementAttributesList = restTemplate.exchange(path, HttpMethod.GET, + new HttpEntity<>(headers), new ParameterizedTypeReference>() { }).getBody(); + return Objects.requireNonNullElseGet(elementAttributesList, Collections::emptyList); } public void deleteElement(UUID id, String userId) { @@ -156,8 +123,9 @@ private IDirectoryElementsService getGenericService(String type) { IDirectoryElementsService iDirectoryElementsService = genericServices.get(type); if (iDirectoryElementsService == null) { throw new ExploreException(UNKNOWN_ELEMENT_TYPE, "Unknown element type " + type); + } else { + return iDirectoryElementsService; } - return iDirectoryElementsService; } public List getElementsMetadata(List ids, List elementTypes, @@ -170,28 +138,24 @@ public List getElementsMetadata(List ids, List IDirectoryElementsService service = getGenericService(elementAttribute.getKey()); listOfElements.addAll(service.completeElementAttribute(elementAttribute.getValue())); } - if (!CollectionUtils.isEmpty(equipmentTypes) && !listOfElements.isEmpty()) { listOfElements = listOfElements.stream() .filter(element -> "DIRECTORY".equals(element.getType()) || equipmentTypes.contains(element.getSpecificMetadata().get("equipmentType"))) .collect(Collectors.toList()); } - return listOfElements; } public void updateElement(UUID elementUuid, ElementAttributes elementAttributes, String userId) { - String path = UriComponentsBuilder - .fromPath(ELEMENTS_SERVER_ROOT_PATH + "/{elementUuid}") + String path = UriComponentsBuilder.fromPath("/elements/{elementUuid}") .buildAndExpand(elementUuid) .toUriString(); HttpHeaders headers = new HttpHeaders(); headers.set(HEADER_USER_ID, userId); headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity httpEntity = new HttpEntity<>(elementAttributes, headers); - restTemplate.exchange(directoryServerBaseUri + path, HttpMethod.PUT, httpEntity, Void.class); + restTemplate.exchange(path, HttpMethod.PUT, httpEntity, Void.class); } // TODO get id/type recursively then do batch delete diff --git a/src/main/java/org/gridsuite/explore/server/services/FilterService.java b/src/main/java/org/gridsuite/explore/server/services/FilterService.java index c1e9dc86..de245522 100644 --- a/src/main/java/org/gridsuite/explore/server/services/FilterService.java +++ b/src/main/java/org/gridsuite/explore/server/services/FilterService.java @@ -7,8 +7,12 @@ package org.gridsuite.explore.server.services; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.*; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; @@ -23,91 +27,68 @@ */ @Service public class FilterService implements IDirectoryElementsService { - private static final String FILTER_SERVER_API_VERSION = "v1"; - - private static final String DELIMITER = "/"; - private static final String HEADER_USER_ID = "userId"; - - private String filterServerBaseUri; - private final RestTemplate restTemplate; @Autowired - public FilterService(RestTemplate restTemplate, RemoteServicesProperties remoteServicesProperties) { - this.filterServerBaseUri = remoteServicesProperties.getServiceUri("filter-server"); - this.restTemplate = restTemplate; - } - - public void setFilterServerBaseUri(String filterServerBaseUri) { - this.filterServerBaseUri = filterServerBaseUri; + public FilterService(RestTemplateBuilder restTemplateBuilder, RemoteServicesProperties remoteServicesProperties) { + this.restTemplate = restTemplateBuilder.rootUri(remoteServicesProperties.getServiceUri("filter-server") + "/v1").build(); } public void replaceFilterWithScript(UUID id, String userId) { - String path = UriComponentsBuilder - .fromPath(DELIMITER + FILTER_SERVER_API_VERSION + "/filters/{id}/replace-with-script") + String path = UriComponentsBuilder.fromPath("/filters/{id}/replace-with-script") .buildAndExpand(id) .toUriString(); - HttpHeaders headers = new HttpHeaders(); - headers.set(HEADER_USER_ID, userId); - restTemplate.exchange(filterServerBaseUri + path, HttpMethod.PUT, new HttpEntity<>(headers), Void.class); + HttpHeaders headers = getHeaders(userId); + restTemplate.exchange(path, HttpMethod.PUT, new HttpEntity<>(headers), Void.class); } public void insertNewScriptFromFilter(UUID id, UUID newId) { - String path = UriComponentsBuilder - .fromPath(DELIMITER + FILTER_SERVER_API_VERSION + "/filters/{id}/new-script?newId={newId}") - .buildAndExpand(id, newId) + String path = UriComponentsBuilder.fromPath("/filters/{id}/new-script") + .queryParam("newId", newId) + .buildAndExpand(id) .toUriString(); - restTemplate.exchange(filterServerBaseUri + path, HttpMethod.POST, null, Void.class); + restTemplate.exchange(path, HttpMethod.POST, null, Void.class); } @Override public void delete(UUID id, String userId) { - String path = UriComponentsBuilder.fromPath(DELIMITER + FILTER_SERVER_API_VERSION + "/filters/{id}") + String path = UriComponentsBuilder.fromPath("/filters/{id}") .buildAndExpand(id) .toUriString(); - restTemplate.exchange(filterServerBaseUri + path, HttpMethod.DELETE, new HttpEntity<>(getHeaders(userId)), - Void.class); + restTemplate.exchange(path, HttpMethod.DELETE, new HttpEntity<>(getHeaders(userId)), Void.class); } public void insertFilter(String filter, UUID filterId, String userId) { - String path = UriComponentsBuilder.fromPath(DELIMITER + FILTER_SERVER_API_VERSION + "/filters?id={id}") - .buildAndExpand(filterId) + String path = UriComponentsBuilder.fromPath("/filters") + .queryParam("id", filterId) .toUriString(); - HttpHeaders headers = getHeaders(userId); - headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity httpEntity = new HttpEntity<>(filter, headers); - restTemplate.exchange(filterServerBaseUri + path, HttpMethod.POST, httpEntity, Void.class); + HttpEntity httpEntity = getHttpEntityWithUserHeaderAndJsonMediaType(filter, userId); + restTemplate.exchange(path, HttpMethod.POST, httpEntity, Void.class); } public void insertFilter(UUID sourceFilterId, UUID filterId, String userId) { - String path = UriComponentsBuilder.fromPath(DELIMITER + FILTER_SERVER_API_VERSION + "/filters") + String path = UriComponentsBuilder.fromPath("/filters") .queryParam("duplicateFrom", sourceFilterId) .queryParam("id", filterId) .toUriString(); - restTemplate.exchange(filterServerBaseUri + path, HttpMethod.POST, new HttpEntity<>(getHeaders(userId)), - Void.class); + restTemplate.exchange(path, HttpMethod.POST, new HttpEntity<>(getHeaders(userId)), Void.class); } @Override public List> getMetadata(List filtersUuids) { var ids = filtersUuids.stream().map(UUID::toString).collect(Collectors.joining(",")); - String path = UriComponentsBuilder - .fromPath(DELIMITER + FILTER_SERVER_API_VERSION + "/filters/metadata" + "?ids=" + ids) - .buildAndExpand() + String path = UriComponentsBuilder.fromPath("/filters/metadata") + .queryParam("ids", ids) .toUriString(); - return restTemplate.exchange(filterServerBaseUri + path, HttpMethod.GET, null, - new ParameterizedTypeReference>>() { - }).getBody(); + return restTemplate.exchange(path, HttpMethod.GET, null, + new ParameterizedTypeReference>>() { }).getBody(); } public void updateFilter(UUID id, String filter, String userId) { - - String path = UriComponentsBuilder.fromPath(DELIMITER + FILTER_SERVER_API_VERSION + "/filters/{id}") + String path = UriComponentsBuilder.fromPath("/filters/{id}") .buildAndExpand(id) .toUriString(); - - restTemplate.exchange(filterServerBaseUri + path, HttpMethod.PUT, getHttpEntityWithUserHeaderAndJsonMediaType(userId, filter), Void.class); - + restTemplate.exchange(path, HttpMethod.PUT, getHttpEntityWithUserHeaderAndJsonMediaType(userId, filter), Void.class); } private HttpHeaders getHeaders(String userId) { @@ -121,5 +102,4 @@ private HttpEntity getHttpEntityWithUserHeaderAndJsonMediaType(String us headers.setContentType(MediaType.APPLICATION_JSON); return new HttpEntity<>(content, headers); } - } diff --git a/src/main/java/org/gridsuite/explore/server/services/ParametersService.java b/src/main/java/org/gridsuite/explore/server/services/ParametersService.java index 96d065b6..934c6bdb 100644 --- a/src/main/java/org/gridsuite/explore/server/services/ParametersService.java +++ b/src/main/java/org/gridsuite/explore/server/services/ParametersService.java @@ -9,12 +9,16 @@ import org.gridsuite.explore.server.dto.ElementAttributes; import org.gridsuite.explore.server.utils.ParametersType; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; -import org.springframework.http.*; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -24,78 +28,48 @@ */ @Service public class ParametersService implements IDirectoryElementsService { - private static final String SERVER_API_VERSION = "v1"; + private final DirectoryService directoryService; - private static final String DELIMITER = "/"; - private static final String HEADER_USER_ID = "userId"; - - private final RestTemplate restTemplate; - - private DirectoryService directoryService; - - private final Map genericParametersServices = Map.of(ParametersType.VOLTAGE_INIT_PARAMETERS, "voltage-init-server"); - - private RemoteServicesProperties remoteServicesProperties; + private final Map genericParametersServices; @Autowired - public ParametersService(RemoteServicesProperties remoteServicesProperties, @Lazy DirectoryService directoryService, RestTemplate restTemplate) { - this.restTemplate = restTemplate; - this.remoteServicesProperties = remoteServicesProperties; + public ParametersService(RemoteServicesProperties remoteServicesProperties, DirectoryService directoryService, RestTemplateBuilder restTemplateBuilder) { + genericParametersServices = Map.of( + ParametersType.VOLTAGE_INIT_PARAMETERS, restTemplateBuilder.rootUri(remoteServicesProperties.getServiceUri(ParametersType.VOLTAGE_INIT_PARAMETERS.name().toLowerCase(Locale.ENGLISH)) + "/v1").build() + ); this.directoryService = directoryService; } public UUID createParameters(String parameters, ParametersType parametersType) { - String parametersServerBaseUri = remoteServicesProperties.getServiceUri(genericParametersServices.get(parametersType)); Objects.requireNonNull(parameters); - - var path = UriComponentsBuilder - .fromPath(DELIMITER + SERVER_API_VERSION + "/parameters") - .buildAndExpand() + var path = UriComponentsBuilder.fromPath("/parameters") .toUriString(); - HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity httpEntity = new HttpEntity<>(parameters, headers); - - UUID parametersUuid; - - parametersUuid = restTemplate.exchange(parametersServerBaseUri + path, HttpMethod.POST, httpEntity, UUID.class).getBody(); - - return parametersUuid; + return genericParametersServices.get(parametersType).exchange(path, HttpMethod.POST, httpEntity, UUID.class).getBody(); } public void updateParameters(UUID parametersUuid, String parameters, ParametersType parametersType) { - String parametersServerBaseUri = remoteServicesProperties.getServiceUri(genericParametersServices.get(parametersType)); Objects.requireNonNull(parameters); - - var path = UriComponentsBuilder - .fromPath(DELIMITER + SERVER_API_VERSION + "/parameters/{parametersUuid}") + var path = UriComponentsBuilder.fromPath("/parameters/{parametersUuid}") .buildAndExpand(parametersUuid) .toUriString(); - HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity httpEntity = new HttpEntity<>(parameters, headers); - - restTemplate.exchange(parametersServerBaseUri + path, HttpMethod.PUT, httpEntity, UUID.class); + genericParametersServices.get(parametersType).exchange(path, HttpMethod.PUT, httpEntity, UUID.class); } @Override public void delete(UUID parametersUuid, String userId) { ElementAttributes elementAttributes = directoryService.getElementInfos(parametersUuid); ParametersType parametersType = ParametersType.valueOf(elementAttributes.getType()); - String parametersServerBaseUri = remoteServicesProperties.getServiceUri(genericParametersServices.get(parametersType)); - String path = UriComponentsBuilder.fromPath(DELIMITER + SERVER_API_VERSION + "/parameters/{parametersUuid}") + String path = UriComponentsBuilder.fromPath("/parameters/{parametersUuid}") .buildAndExpand(parametersUuid) .toUriString(); - HttpHeaders headers = new HttpHeaders(); headers.add(HEADER_USER_ID, userId); - - restTemplate.exchange(parametersServerBaseUri + path, HttpMethod.DELETE, new HttpEntity<>(headers), - Void.class); + genericParametersServices.get(parametersType).exchange(path, HttpMethod.DELETE, new HttpEntity<>(headers), Void.class); } - } diff --git a/src/main/java/org/gridsuite/explore/server/services/StudyService.java b/src/main/java/org/gridsuite/explore/server/services/StudyService.java index 6304e37c..b874cd59 100644 --- a/src/main/java/org/gridsuite/explore/server/services/StudyService.java +++ b/src/main/java/org/gridsuite/explore/server/services/StudyService.java @@ -7,13 +7,19 @@ package org.gridsuite.explore.server.services; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.*; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.UUID; import java.util.stream.Collectors; /** @@ -21,67 +27,49 @@ */ @Service public class StudyService implements IDirectoryElementsService { - private static final String STUDY_SERVER_API_VERSION = "v1"; - - private static final String DELIMITER = "/"; private final RestTemplate restTemplate; - private String studyServerBaseUri; @Autowired - public StudyService(RestTemplate restTemplate, RemoteServicesProperties remoteServicesProperties) { - this.studyServerBaseUri = remoteServicesProperties.getServiceUri("study-server"); - this.restTemplate = restTemplate; - } - - public void setStudyServerBaseUri(String studyServerBaseUri) { - this.studyServerBaseUri = studyServerBaseUri; + public StudyService(RestTemplateBuilder restTemplateBuilder, RemoteServicesProperties remoteServicesProperties) { + this.restTemplate = restTemplateBuilder.rootUri(remoteServicesProperties.getServiceUri("study-server") + "/v1").build(); } public void insertStudyWithExistingCaseFile(UUID studyUuid, String userId, UUID caseUuid, Map importParams, Boolean duplicateCase) { - String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_SERVER_API_VERSION + - "/studies/cases/{caseUuid}") + String path = UriComponentsBuilder.fromPath("/studies/cases/{caseUuid}") .queryParam("studyUuid", studyUuid) .queryParam("duplicateCase", duplicateCase) .buildAndExpand(caseUuid) .toUriString(); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.add(HEADER_USER_ID, userId); - HttpEntity> request = new HttpEntity<>( - importParams, headers); - restTemplate.exchange(studyServerBaseUri + path, HttpMethod.POST, request, Void.class); + HttpHeaders headers = getHeaders(userId); + HttpEntity> request = new HttpEntity<>(importParams, headers); + restTemplate.exchange(path, HttpMethod.POST, request, Void.class); } public void duplicateStudy(UUID sourceStudyUuid, UUID studyUuid, String userId) { - String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_SERVER_API_VERSION + - "/studies") + String path = UriComponentsBuilder.fromPath("/studies") .queryParam("duplicateFrom", sourceStudyUuid) .queryParam("studyUuid", studyUuid) .toUriString(); - restTemplate.exchange(studyServerBaseUri + path, HttpMethod.POST, new HttpEntity<>(getHeaders(userId)), - Void.class); + restTemplate.exchange(path, HttpMethod.POST, new HttpEntity<>(getHeaders(userId)), Void.class); } @Override public void delete(UUID studyUuid, String userId) { - String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_SERVER_API_VERSION + "/studies/{studyUuid}") + String path = UriComponentsBuilder.fromPath("/studies/{studyUuid}") .buildAndExpand(studyUuid) .toUriString(); - restTemplate.exchange(studyServerBaseUri + path, HttpMethod.DELETE, new HttpEntity<>(getHeaders(userId)), - Void.class); + restTemplate.exchange(path, HttpMethod.DELETE, new HttpEntity<>(getHeaders(userId)), Void.class); } @Override public List> getMetadata(List studiesUuids) { var ids = studiesUuids.stream().map(UUID::toString).collect(Collectors.joining(",")); - String path = UriComponentsBuilder - .fromPath(DELIMITER + STUDY_SERVER_API_VERSION + "/studies/metadata" + "?ids=" + ids) - .buildAndExpand() + String path = UriComponentsBuilder.fromPath("/studies/metadata") + .queryParam("ids", ids) .toUriString(); - return restTemplate.exchange(studyServerBaseUri + path, HttpMethod.GET, null, - new ParameterizedTypeReference>>() { - }).getBody(); + return restTemplate.exchange(path, HttpMethod.GET, null, + new ParameterizedTypeReference>>() { }).getBody(); } private HttpHeaders getHeaders(String userId) { diff --git a/src/test/java/org/gridsuite/explore/server/ExploreTest.java b/src/test/java/org/gridsuite/explore/server/ExploreTest.java index 4ffd5b44..8f1a0cd5 100644 --- a/src/test/java/org/gridsuite/explore/server/ExploreTest.java +++ b/src/test/java/org/gridsuite/explore/server/ExploreTest.java @@ -8,40 +8,34 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.SneakyThrows; -import okhttp3.HttpUrl; -import okhttp3.mockwebserver.Dispatcher; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import okio.Buffer; import org.gridsuite.explore.server.dto.AccessRightsAttributes; import org.gridsuite.explore.server.dto.ElementAttributes; -import org.gridsuite.explore.server.services.*; import org.gridsuite.explore.server.utils.ContingencyListType; import org.gridsuite.explore.server.utils.ParametersType; -import org.gridsuite.explore.server.utils.TestUtils; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.autoconfigure.core.AutoConfigureCache; +import org.springframework.boot.test.autoconfigure.web.client.AutoConfigureWebClient; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.client.MockRestServiceServer; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.util.ResourceUtils; import java.io.FileInputStream; -import java.io.IOException; import java.io.InputStream; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.assertj.core.api.Assertions.*; +import static org.gridsuite.explore.server.services.MockRemoteServices.*; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @@ -50,588 +44,656 @@ /** * @author Etienne Homer */ -@RunWith(SpringRunner.class) -@AutoConfigureMockMvc -@SpringBootTest -@ContextConfiguration(classes = {ExploreApplication.class}) +@AutoConfigureMockMvc //we want to test the controller +@AutoConfigureWebClient @AutoConfigureCache //we mock http clients +@SpringBootTest(classes = {ExploreApplication.class, TestConfig.class}) +@ExtendWith(ExploreTestExtension.class) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@DisplayName("Explore Server tests") public class ExploreTest { - private static final String TEST_FILE = "testCase.xiidm"; - private static final String TEST_FILE_WITH_ERRORS = "testCase_with_errors.xiidm"; - - private static final String TEST_INCORRECT_FILE = "application-default.yml"; - private static final UUID CASE_UUID = UUID.randomUUID(); - private static final UUID NON_EXISTING_CASE_UUID = UUID.randomUUID(); - private static final UUID PARENT_DIRECTORY_UUID = UUID.randomUUID(); - private static final UUID PARENT_DIRECTORY_WITH_ERROR_UUID = UUID.randomUUID(); - private static final UUID PRIVATE_STUDY_UUID = UUID.randomUUID(); - private static final UUID PUBLIC_STUDY_UUID = UUID.randomUUID(); - private static final UUID FILTER_UUID = UUID.randomUUID(); - private static final UUID FILTER_UUID_2 = UUID.randomUUID(); - private static final UUID CONTINGENCY_LIST_UUID = UUID.randomUUID(); - private static final UUID INVALID_ELEMENT_UUID = UUID.randomUUID(); - private static final UUID PARAMETERS_UUID = UUID.randomUUID(); - private static final String STUDY_ERROR_NAME = "studyInError"; - private static final String STUDY1 = "study1"; - private static final String CASE1 = "case1"; - private static final String FILTER1 = "filter1"; - private static final String USER1 = "user1"; - public static final String FILTER_CONTINGENCY_LIST = "filterContingencyList"; - public static final String FILTER_CONTINGENCY_LIST_2 = "filterContingencyList2"; - public static final String FILTER = "FILTER"; - private Map specificMetadata = new HashMap<>(); - private Map specificMetadata2 = new HashMap<>(); - private Map caseSpecificMetadata = new HashMap<>(); - - private static final UUID SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID = UUID.randomUUID(); + public static final UUID SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID = UUID.randomUUID(); + public static final String STUDY_ERROR_NAME = "studyInError"; + public static final String CASE1 = "case1"; + public static final String FILTER1 = "filter1"; @Autowired private MockMvc mockMvc; - @Autowired - private DirectoryService directoryService; - @Autowired - private ContingencyListService contingencyListService; - @Autowired - private FilterService filterService; - @Autowired - private StudyService studyService; - @Autowired - private CaseService caseService; - @Autowired - private RemoteServicesProperties remoteServicesProperties; + @Autowired @Qualifier("mockRestSrvCaseService") + private MockRestServiceServer mockRestCaseService; + @Autowired @Qualifier("mockRestSrvContingencyListService") + private MockRestServiceServer mockRestContingencyListService; + @Autowired @Qualifier("mockRestSrvDirectoryService") + private MockRestServiceServer mockRestDirectoryService; + @Autowired @Qualifier("mockRestSrvFilterService") + private MockRestServiceServer mockRestFilterService; + @Autowired @Qualifier("mockRestSrvStudyService") + private MockRestServiceServer mockRestStudyService; + @Autowired @Qualifier("mockRestSrvParametersService") + private Map mockRestParametersServices; @Autowired private ObjectMapper mapper; - private MockWebServer server; - - @Before - public void setup() throws IOException { - server = new MockWebServer(); - - // Start the server. - server.start(); - - // Ask the server for its URL. You'll need this to make HTTP requests. - HttpUrl baseHttpUrl = server.url(""); - String baseUrl = baseHttpUrl.toString().substring(0, baseHttpUrl.toString().length() - 1); - - directoryService.setDirectoryServerBaseUri(baseUrl); - studyService.setStudyServerBaseUri(baseUrl); - filterService.setFilterServerBaseUri(baseUrl); - contingencyListService.setActionsServerBaseUri(baseUrl); - caseService.setBaseUri(baseUrl); - remoteServicesProperties.getServices().forEach(s -> s.setBaseUri(baseUrl)); - specificMetadata.put("id", FILTER_UUID); - - specificMetadata2.put("equipmentType", "LINE"); - specificMetadata2.put("id", FILTER_UUID_2); - - caseSpecificMetadata.put("uuid", CASE_UUID); - caseSpecificMetadata.put("name", TEST_FILE); - caseSpecificMetadata.put("format", "XIIDM"); - - String privateStudyAttributesAsString = mapper.writeValueAsString(new ElementAttributes(PRIVATE_STUDY_UUID, STUDY1, "STUDY", new AccessRightsAttributes(true), USER1, 0, null)); - String listOfPrivateStudyAttributesAsString = mapper.writeValueAsString(List.of(new ElementAttributes(PRIVATE_STUDY_UUID, STUDY1, "STUDY", new AccessRightsAttributes(true), USER1, 0, null))); - String publicStudyAttributesAsString = mapper.writeValueAsString(new ElementAttributes(PUBLIC_STUDY_UUID, STUDY1, "STUDY", new AccessRightsAttributes(false), USER1, 0, null)); - String invalidElementAsString = mapper.writeValueAsString(new ElementAttributes(INVALID_ELEMENT_UUID, "invalidElementName", "INVALID", new AccessRightsAttributes(false), USER1, 0, null)); - String formContingencyListAttributesAsString = mapper.writeValueAsString(new ElementAttributes(CONTINGENCY_LIST_UUID, FILTER_CONTINGENCY_LIST, "CONTINGENCY_LIST", new AccessRightsAttributes(true), USER1, 0, null)); - String listOfFormContingencyListAttributesAsString = mapper.writeValueAsString(List.of(new ElementAttributes(CONTINGENCY_LIST_UUID, FILTER_CONTINGENCY_LIST, "CONTINGENCY_LIST", new AccessRightsAttributes(true), USER1, 0, null))); - String filterAttributesAsString = mapper.writeValueAsString(new ElementAttributes(FILTER_UUID, FILTER_CONTINGENCY_LIST, FILTER, new AccessRightsAttributes(true), USER1, 0, null)); - String filter2AttributesAsString = mapper.writeValueAsString(new ElementAttributes(FILTER_UUID_2, FILTER_CONTINGENCY_LIST_2, FILTER, new AccessRightsAttributes(true), USER1, 0, null)); - String listOfFilterAttributesAsString = mapper.writeValueAsString(List.of(new ElementAttributes(FILTER_UUID, FILTER_CONTINGENCY_LIST, FILTER, new AccessRightsAttributes(true), USER1, 0, null))); - String directoryAttributesAsString = mapper.writeValueAsString(new ElementAttributes(PARENT_DIRECTORY_UUID, "directory", "DIRECTORY", new AccessRightsAttributes(true), USER1, 0, null)); - String caseElementAttributesAsString = mapper.writeValueAsString(new ElementAttributes(CASE_UUID, "case", "CASE", new AccessRightsAttributes(true), USER1, 0L, null)); - String parametersElementAttributesAsString = mapper.writeValueAsString(new ElementAttributes(PARAMETERS_UUID, "voltageInitParametersName", ParametersType.VOLTAGE_INIT_PARAMETERS.name(), new AccessRightsAttributes(true), USER1, 0, null)); - String listElementsAttributesAsString = "[" + filterAttributesAsString + "," + privateStudyAttributesAsString + "," + formContingencyListAttributesAsString + "]"; - String caseInfosAttributesAsString = mapper.writeValueAsString(List.of(caseSpecificMetadata)); - - final Dispatcher dispatcher = new Dispatcher() { - @SneakyThrows - @Override - public MockResponse dispatch(RecordedRequest request) { - String path = Objects.requireNonNull(request.getPath()); - Buffer body = request.getBody(); - - if (path.matches("/v1/studies/cases/" + NON_EXISTING_CASE_UUID + ".*") && "POST".equals(request.getMethod())) { - return new MockResponse().setResponseCode(404); - } else if (path.matches("/v1/studies.*") && "POST".equals(request.getMethod())) { - String bodyStr = body.readUtf8(); - if (bodyStr.contains("filename=\"" + TEST_FILE_WITH_ERRORS + "\"")) { // import file with errors - return new MockResponse().setResponseCode(409); - } else { - return new MockResponse().setResponseCode(200); - } - } else if (path.matches("/v1/cases.*") && "POST".equals(request.getMethod())) { - String bodyStr = body.readUtf8(); - if (bodyStr.contains("filename=\"" + TEST_FILE_WITH_ERRORS + "\"")) { // import file with errors - return new MockResponse().setResponseCode(409).setBody("invalid file"); - } else if (bodyStr.contains("filename=\"" + TEST_INCORRECT_FILE + "\"")) { // import file with errors - return new MockResponse().setResponseCode(422).setBody("file with bad extension"); - } else { - return new MockResponse().setResponseCode(200); - } - } else if (path.matches("/v1/directories/" + PARENT_DIRECTORY_UUID + "/elements") && "POST".equals(request.getMethod())) { - return new MockResponse().setBody(privateStudyAttributesAsString).setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/directories/" + PARENT_DIRECTORY_WITH_ERROR_UUID + "/elements") && "POST".equals(request.getMethod())) { - return new MockResponse().setResponseCode(500); - } else if (path.matches("/v1/elements/" + CONTINGENCY_LIST_UUID) && "GET".equals(request.getMethod())) { - return new MockResponse().setBody(formContingencyListAttributesAsString).setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.equals("/v1/elements/" + CONTINGENCY_LIST_UUID + "/notification?type=UPDATE_DIRECTORY")) { - return new MockResponse().setBody(formContingencyListAttributesAsString).setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/elements/" + FILTER_UUID) && "GET".equals(request.getMethod())) { - return new MockResponse().setBody(filterAttributesAsString).setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.equals("/v1/elements/" + FILTER_UUID + "/notification?type=UPDATE_DIRECTORY")) { - return new MockResponse().setBody(filterAttributesAsString).setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/elements/" + CASE_UUID) && "GET".equals(request.getMethod())) { - return new MockResponse().setBody(caseElementAttributesAsString).setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/elements/" + PRIVATE_STUDY_UUID) && "GET".equals(request.getMethod())) { - return new MockResponse().setBody(privateStudyAttributesAsString).setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/elements/" + PUBLIC_STUDY_UUID) && "GET".equals(request.getMethod())) { - return new MockResponse().setBody(publicStudyAttributesAsString).setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/elements/" + PARAMETERS_UUID) && "GET".equals(request.getMethod())) { - return new MockResponse().setBody(parametersElementAttributesAsString).setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/elements\\?ids=" + FILTER_UUID + "," + FILTER_UUID_2 + "&elementTypes=FILTER") && "GET".equals(request.getMethod())) { - return new MockResponse().setBody("[" + filterAttributesAsString + "," + filter2AttributesAsString + "]") - .setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/elements\\?ids=" + CASE_UUID) && "GET".equals(request.getMethod())) { - return new MockResponse().setBody("[" + caseElementAttributesAsString + "]") - .setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/filters/metadata\\?ids=" + FILTER_UUID + "," + FILTER_UUID_2) && "GET".equals(request.getMethod())) { - return new MockResponse().setBody("[" + mapper.writeValueAsString(specificMetadata) + "," + mapper.writeValueAsString(specificMetadata2) + "]") - .setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/elements\\?ids=" + FILTER_UUID + "," + PRIVATE_STUDY_UUID + "," + CONTINGENCY_LIST_UUID) && "GET".equals(request.getMethod())) { - return new MockResponse().setBody(listElementsAttributesAsString).setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/elements/.*") && "PUT".equals(request.getMethod())) { - return new MockResponse().setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/contingency-lists/metadata[?]ids=" + CONTINGENCY_LIST_UUID) && "GET".equals(request.getMethod())) { - return new MockResponse().setBody(listOfFormContingencyListAttributesAsString.replace("elementUuid", "id")).setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/script-contingency-lists\\?id=" + PARENT_DIRECTORY_WITH_ERROR_UUID) && "POST".equals(request.getMethod())) { - return new MockResponse().setResponseCode(500); - } else if (path.matches("/v1/script-contingency-lists.*") && "POST".equals(request.getMethod())) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/form-contingency-lists.*") && "POST".equals(request.getMethod())) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/identifier-contingency-lists.*") && "POST".equals(request.getMethod())) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/form-contingency-lists/.*/new-script/.*") && "POST".equals(request.getMethod())) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/filters/.*/new-script.*") && "POST".equals(request.getMethod())) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/filters.*") && "POST".equals(request.getMethod())) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/filters\\?id=.*") && "POST".equals(request.getMethod())) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/filters/.*/replace-with-script") && "PUT".equals(request.getMethod())) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/filters/.*") && "PUT".equals(request.getMethod())) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/script-contingency-lists/.*") && "PUT".equals(request.getMethod())) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/form-contingency-lists/.*") && "PUT".equals(request.getMethod())) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/identifier-contingency-lists/.*") && "PUT".equals(request.getMethod())) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/parameters.*")) { - return new MockResponse().setResponseCode(200); - } else if ("GET".equals(request.getMethod())) { - if (path.matches("/v1/elements/" + INVALID_ELEMENT_UUID)) { - return new MockResponse().setBody(invalidElementAsString).setResponseCode(200).addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/directories/" + PARENT_DIRECTORY_UUID + "/elements")) { - return new MockResponse().setResponseCode(200).addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/elements/" + PARENT_DIRECTORY_UUID)) { - return new MockResponse().setBody(directoryAttributesAsString).setResponseCode(200).addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/filters/metadata[?]ids=" + FILTER_UUID)) { - return new MockResponse().setBody(listOfFilterAttributesAsString.replace("elementUuid", "id")).setResponseCode(200).addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/cases/metadata[?]ids=" + CASE_UUID)) { - return new MockResponse().setBody(caseInfosAttributesAsString).setResponseCode(200).addHeader("Content-Type", "application/json; charset=utf-8"); - } else if (path.matches("/v1/studies/metadata[?]ids=" + PRIVATE_STUDY_UUID)) { - return new MockResponse().setBody(listOfPrivateStudyAttributesAsString.replace("elementUuid", "id")).setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8"); - } - } else if ("DELETE".equals(request.getMethod())) { - if (path.matches("/v1/filters/" + FILTER_UUID)) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/studies/" + PRIVATE_STUDY_UUID)) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/contingency-lists/" + CONTINGENCY_LIST_UUID)) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/elements/" + INVALID_ELEMENT_UUID)) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/elements/" + PRIVATE_STUDY_UUID)) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/elements/" + FILTER_UUID)) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/elements/" + CONTINGENCY_LIST_UUID)) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/elements/" + PARENT_DIRECTORY_UUID)) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/elements/" + PARAMETERS_UUID)) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/(cases|elements)/" + CASE_UUID)) { - return new MockResponse().setResponseCode(200); - } else if (path.matches("/v1/parameters/" + PARAMETERS_UUID)) { - return new MockResponse().setResponseCode(200); - } - return new MockResponse().setResponseCode(404); - } - return new MockResponse().setResponseCode(418); - } - }; - server.setDispatcher(dispatcher); - } - @Test - public void testCreateStudyFromExistingCase() throws Exception { - mockMvc.perform(post("/v1/explore/studies/" + STUDY1 + "/cases/" + CASE_UUID + "?description=desc&parentDirectoryUuid=" + PARENT_DIRECTORY_UUID) - .param("duplicateCase", "false") - .header("userId", "userId") - .contentType(MediaType.APPLICATION_JSON) - ).andExpect(status().isOk()); + private MockCaseService caseService; + private MockContingencyListService contingencyListService; + private MockDirectoryService directoryService; + private MockFilterService filterService; + private MockStudyService studyService; + private MockParametersService parametersService; + + @BeforeAll + void init() { + caseService = new MockCaseService(mockRestCaseService, mapper); + contingencyListService = new MockContingencyListService(mockRestContingencyListService, mapper); + directoryService = new MockDirectoryService(mockRestDirectoryService, mapper); + filterService = new MockFilterService(mockRestFilterService, mapper); + studyService = new MockStudyService(mockRestStudyService, mapper); + parametersService = new MockParametersService(mockRestParametersServices, mapper); } - @Test - public void testCreateStudyFromExistingCaseError() throws Exception { - mockMvc.perform(post("/v1/explore/studies/" + STUDY1 + "/cases/" + NON_EXISTING_CASE_UUID + "?description=desc&parentDirectoryUuid=" + PARENT_DIRECTORY_UUID) - .header("userId", USER1) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isNotFound()); + private void expectNoMoreRestCall() { + caseService.expectNoMoreCall(); + contingencyListService.expectNoMoreCall(); + directoryService.expectNoMoreCall(); + filterService.expectNoMoreCall(); + studyService.expectNoMoreCall(); + parametersService.expectNoMoreCall(); } - @Test - public void testCreateCase() throws Exception { - try (InputStream is = new FileInputStream(ResourceUtils.getFile("classpath:" + TEST_FILE))) { - MockMultipartFile mockFile = new MockMultipartFile("caseFile", TEST_FILE, "text/xml", is); + @BeforeEach + void setup() { + mockRestCaseService.reset(); + mockRestContingencyListService.reset(); + mockRestDirectoryService.reset(); + mockRestFilterService.reset(); + mockRestStudyService.reset(); + mockRestParametersServices.values().forEach(MockRestServiceServer::reset); + } - mockMvc.perform(multipart("/v1/explore/cases/{caseName}?description={description}&parentDirectoryUuid={parentDirectoryUuid}", - STUDY1, "description", PARENT_DIRECTORY_UUID).file(mockFile) - .header("userId", USER1) - .contentType(MediaType.MULTIPART_FORM_DATA) - ) - .andExpect(status().isOk()); - } + @AfterEach + void verifyRequestsMockRestCaseService() { + mockRestCaseService.verify(); } - @Test - public void testCaseCreationError() throws Exception { - try (InputStream is = new FileInputStream(ResourceUtils.getFile("classpath:" + TEST_FILE_WITH_ERRORS))) { - MockMultipartFile mockFile = new MockMultipartFile("caseFile", TEST_FILE_WITH_ERRORS, "text/xml", is); + @AfterEach + void verifyRequestsMockRestContingencyListService() { + mockRestContingencyListService.verify(); + } - mockMvc.perform(multipart("/v1/explore/cases/{caseName}?description={description}&parentDirectoryUuid={parentDirectoryUuid}", - STUDY_ERROR_NAME, "description", PARENT_DIRECTORY_UUID).file(mockFile) - .header("userId", USER1) - .contentType(MediaType.MULTIPART_FORM_DATA)) - .andExpect(status().isBadRequest()); - } + @AfterEach + void verifyRequestsMockRestDirectoryService() { + mockRestDirectoryService.verify(); } - @Test - public void testCreateScriptContingencyList() throws Exception { - mockMvc.perform(post("/v1/explore/script-contingency-lists/{listName}?&parentDirectoryUuid={parentDirectoryUuid}&description={description}}", - "contingencyListScriptName", PARENT_DIRECTORY_UUID, null) - .header("userId", USER1) - .contentType(MediaType.APPLICATION_JSON) - .content("Contingency list content") - ).andExpect(status().isOk()); + @AfterEach + void verifyRequestsMockRestFilterService() { + mockRestFilterService.verify(); } - @Test - public void testCreateScriptContingencyListError() throws Exception { - mockMvc.perform(post("/v1/explore/script-contingency-lists/{listName}?&parentDirectoryUuid={parentDirectoryUuid}&description={description}}", - "contingencyListScriptName", PARENT_DIRECTORY_WITH_ERROR_UUID, null) - .header("userId", USER1) - .contentType(MediaType.APPLICATION_JSON) - .content("Contingency list content") - ).andExpect(status().isInternalServerError()); + @AfterEach + void verifyRequestsMockRestStudyService() { + mockRestStudyService.verify(); } - @Test - public void testCreateFormContingencyList() throws Exception { - mockMvc.perform(post("/v1/explore/form-contingency-lists/{listName}?parentDirectoryUuid={parentDirectoryUuid}&description={description}", - FILTER_CONTINGENCY_LIST, PARENT_DIRECTORY_UUID, null) - .header("userId", USER1) - .contentType(MediaType.APPLICATION_JSON) - .content("Contingency list content") - ).andExpect(status().isOk()); + @AfterEach + void verifyRequestsMockRestParametersService() { + final List errors = mockRestParametersServices.values().stream().filter(Objects::nonNull) + .map(mockServer -> { + try { + mockServer.verify(); + return null; + } catch (final AssertionError ex) { + return ex; + } + }) + .filter(Objects::nonNull).toList(); + //TODO replace with SoftAssertions when AssertJ updated + if (errors.size() == 1) { + throw errors.get(0); + } else if (errors.size() > 1) { + final AssertionError error = new AssertionError("Some unexpected HTTP call happened"); + //error.setStackTrace(new StackTraceElement[]{Thread.currentThread().getStackTrace()[0]}); + errors.forEach(error::addSuppressed); + throw error; + } } - @Test - public void testCreateIdentifierContingencyList() throws Exception { - mockMvc.perform(post("/v1/explore/identifier-contingency-lists/{listName}?parentDirectoryUuid={parentDirectoryUuid}&description={description}", - "identifierContingencyListName", PARENT_DIRECTORY_UUID, null) - .header("userId", USER1) - .contentType(MediaType.APPLICATION_JSON) - .content("Contingency list content") - ).andExpect(status().isOk()); + @DisplayName("test creation elements") + @Nested + class ExploreTestCreate { + @DisplayName("test creation studies") + @Nested + class ExploreTestCreateStudy { + @Test + void testCreateStudyFromExistingCase() throws Exception { + studyService.expectPostStudies(); //POST /studies/cases/${CASE_UUID}?studyUuid=00000000-0000-0000-0000-000000000000&duplicateCase=false + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/studies/" + STUDY1 + "/cases/" + CASE_UUID + "?description=desc&parentDirectoryUuid=" + PARENT_DIRECTORY_UUID) + .param("duplicateCase", "false") + .header("userId", USER1) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + } + + @Test + void testCreateStudyFromExistingCaseError() throws Exception { + studyService.expectPostStudiesCasesNonExistingCaseUuid(); //POST /studies/cases/${NON_EXISTING_CASE_UUID}?studyUuid=00000000-0000-0000-0000-000000000000&duplicateCase=false + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/studies/" + STUDY1 + "/cases/" + NON_EXISTING_CASE_UUID + "?description=desc&parentDirectoryUuid=" + PARENT_DIRECTORY_UUID) + .header("userId", USER1) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNotFound()); + } + } + + @DisplayName("test creation cases") + @Nested + class ExploreTestCreateCase { + @Test + void testCreateCase() throws Exception { + caseService.expectPostCasesNoIncorrectOrErrorFile(); //POST /cases + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + + try (InputStream is = new FileInputStream(ResourceUtils.getFile("classpath:" + TEST_FILE))) { + MockMultipartFile mockFile = new MockMultipartFile("caseFile", TEST_FILE, "text/xml", is); + + mockMvc.perform(multipart("/v1/explore/cases/{caseName}?description={description}&parentDirectoryUuid={parentDirectoryUuid}", + STUDY1, "description", PARENT_DIRECTORY_UUID) + .file(mockFile) + .header("userId", USER1) + .contentType(MediaType.MULTIPART_FORM_DATA)) + .andExpect(status().isOk()); + } + } + + @Test + void testCaseCreationError() throws Exception { + caseService.expectPostCasesTestFileWithErrors(); //POST /cases + expectNoMoreRestCall(); + + try (InputStream is = new FileInputStream(ResourceUtils.getFile("classpath:" + TEST_FILE_WITH_ERRORS))) { + MockMultipartFile mockFile = new MockMultipartFile("caseFile", TEST_FILE_WITH_ERRORS, "text/xml", is); + + mockMvc.perform(multipart("/v1/explore/cases/{caseName}?description={description}&parentDirectoryUuid={parentDirectoryUuid}", + STUDY_ERROR_NAME, "description", PARENT_DIRECTORY_UUID) + .file(mockFile) + .header("userId", USER1) + .contentType(MediaType.MULTIPART_FORM_DATA)) + .andExpect(status().isBadRequest()); + } + } + + @Test + void testCaseCreationErrorWithBadExtension() throws Exception { + caseService.expectPostCasesTestIncorrectFile(); //POST /cases + expectNoMoreRestCall(); + + try (InputStream is = new FileInputStream(ResourceUtils.getFile("classpath:" + TEST_INCORRECT_FILE))) { + MockMultipartFile mockFile = new MockMultipartFile("caseFile", TEST_INCORRECT_FILE, "text/xml", is); + + mockMvc.perform(multipart("/v1/explore/cases/{caseName}?description={description}&parentDirectoryUuid={parentDirectoryUuid}", + STUDY_ERROR_NAME, "description", PARENT_DIRECTORY_UUID) + .file(mockFile) + .header("userId", USER1) + .contentType(MediaType.MULTIPART_FORM_DATA)) + .andExpect(status().isUnprocessableEntity()); + } + } + } + + @DisplayName("test creation contingency list") + @Nested + class ExploreTestCreateScriptContingencyList { + @Test + void testCreateScriptContingencyList() throws Exception { + contingencyListService.expectPostScriptContingencyLists(); //POST /script-contingency-lists?id=00000000-0000-0000-0000-000000000000 + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/script-contingency-lists/{listName}?&parentDirectoryUuid={parentDirectoryUuid}&description={description}}", + "contingencyListScriptName", PARENT_DIRECTORY_UUID, null) + .header("userId", USER1) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"content\": \"Contingency list content\"}")) + .andExpect(status().isOk()); + } + + @Test + void testCreateScriptContingencyListError() throws Exception { + contingencyListService.expectPostScriptContingencyLists(); //POST /script-contingency-lists?id=00000000-0000-0000-0000-000000000000 + directoryService.expectPostDirectoriesParentDirectoryWithErrorUuidElements(); //POST /directories/${PARENT_DIRECTORY_WITH_ERROR_UUID}/elements + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/script-contingency-lists/{listName}?&parentDirectoryUuid={parentDirectoryUuid}&description={description}}", + "contingencyListScriptName", PARENT_DIRECTORY_WITH_ERROR_UUID, null) + .header("userId", USER1) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"content\": \"Contingency list content\"}")) + .andExpect(status().isInternalServerError()); + } + + @Test + void testCreateFormContingencyList() throws Exception { + contingencyListService.expectPostFormContingencyLists(); //POST /form-contingency-lists?id=00000000-0000-0000-0000-000000000000 + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/form-contingency-lists/{listName}?parentDirectoryUuid={parentDirectoryUuid}&description={description}", + FILTER_CONTINGENCY_LIST, PARENT_DIRECTORY_UUID, null) + .header("userId", USER1) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"content\": \"Contingency list content\"}")) + .andExpect(status().isOk()); + } + + @Test + void testCreateIdentifierContingencyList() throws Exception { + contingencyListService.expectPostIdentifierContingencyLists(); //POST /identifier-contingency-lists?id=00000000-0000-0000-0000-000000000000 + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/identifier-contingency-lists/{listName}?parentDirectoryUuid={parentDirectoryUuid}&description={description}", + "identifierContingencyListName", PARENT_DIRECTORY_UUID, null) + .header("userId", USER1) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"content\": \"Contingency list content\"}")) + .andExpect(status().isOk()); + } + } + + @Test + void testCreateFilter() throws Exception { + filterService.expectPostFiltersIdAny(); //POST /filters?id=00000000-0000-0000-0000-000000000000 + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/filters?name={name}&type={type}&parentDirectoryUuid={parentDirectoryUuid}&description={description}", + "contingencyListScriptName", "", PARENT_DIRECTORY_UUID, null) + .header("userId", USER1) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"content\": \"Filter content\"}")) + .andExpect(status().isOk()); + } + + @Test + void testCreateParameters() throws Exception { + parametersService.expectHttpVoltageInitAny(); //POST http://voltage_init_parameters/v1/parameters + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/parameters?name={name}&type={type}&parentDirectoryUuid={parentDirectoryUuid}", + "", ParametersType.VOLTAGE_INIT_PARAMETERS.name(), PARENT_DIRECTORY_UUID) + .header("userId", USER1) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"content\": \"Parameters content\"}")) + .andExpect(status().isOk()); + } } @Test - public void testNewScriptFromFormContingencyList() throws Exception { + void testNewScriptFromFormContingencyList() throws Exception { + directoryService.expectGetElementsContingencyListUuid(); //GET /elements/${CONTINGENCY_LIST_UUID} + contingencyListService.expectPostFormContingencyListsNewScript(); //POST /form-contingency-lists/${CONTINGENCY_LIST_UUID}/new-script?newId=00000000-0000-0000-0000-000000000000 + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + mockMvc.perform(post("/v1/explore/form-contingency-lists/{id}/new-script/{scriptName}?parentDirectoryUuid={parentDirectoryUuid}", - CONTINGENCY_LIST_UUID, "scriptName", PARENT_DIRECTORY_UUID) - .header("userId", USER1) - ).andExpect(status().isOk()); + CONTINGENCY_LIST_UUID, "scriptName", PARENT_DIRECTORY_UUID) + .header("userId", USER1)) + .andExpect(status().isOk()); } @Test - public void testReplaceFormContingencyListWithScript() throws Exception { - mockMvc.perform(post("/v1/explore/form-contingency-lists/{id}/replace-with-script", - CONTINGENCY_LIST_UUID) - .header("userId", USER1) - ).andExpect(status().isOk()); - } + void testReplaceFormContingencyListWithScript() throws Exception { + directoryService.expectGetElementsContingencyListUuid(); //GET /elements/${CONTINGENCY_LIST_UUID} + contingencyListService.expectPostFormContingencyLists(); //POST /form-contingency-lists/${CONTINGENCY_LIST_UUID}/replace-with-script + directoryService.expectHttpElementsContingencyListUuidNotificationTypeUpdateDirectory(); //POST /elements/${CONTINGENCY_LIST_UUID}/notification?type=UPDATE_DIRECTORY + expectNoMoreRestCall(); - @Test - public void testCreateFilter() throws Exception { - mockMvc.perform(post("/v1/explore/filters?name={name}&type={type}&parentDirectoryUuid={parentDirectoryUuid}&description={description}", - "contingencyListScriptName", "", PARENT_DIRECTORY_UUID, null) - .header("userId", USER1) - .contentType(MediaType.APPLICATION_JSON) - .content("Filter content") - ).andExpect(status().isOk()); + mockMvc.perform(post("/v1/explore/form-contingency-lists/{id}/replace-with-script", CONTINGENCY_LIST_UUID) + .header("userId", USER1)) + .andExpect(status().isOk()); } @Test - public void testCreateParameters() throws Exception { - mockMvc.perform(post("/v1/explore/parameters?name={name}&type={type}&parentDirectoryUuid={parentDirectoryUuid}", - "", ParametersType.VOLTAGE_INIT_PARAMETERS.name(), PARENT_DIRECTORY_UUID) - .header("userId", USER1) - .contentType(MediaType.APPLICATION_JSON) - .content("Parameters content") - ).andExpect(status().isOk()); - } + void testUpdateParameters() throws Exception { + parametersService.expectHttpVoltageInitAny(); //PUT http://voltage_init_parameters/v1/parameters/${PARAMETERS_UUID} + expectNoMoreRestCall(); - @Test - public void testUpdateParameters() throws Exception { mockMvc.perform(put("/v1/explore/parameters/{id}?name={name}&type={type}&parentDirectoryUuid={parentDirectoryUuid}", - PARAMETERS_UUID, "", ParametersType.VOLTAGE_INIT_PARAMETERS.name(), PARENT_DIRECTORY_UUID) - .header("userId", USER1) - .contentType(MediaType.APPLICATION_JSON) - .content("new Parameters content") - ).andExpect(status().isOk()); + PARAMETERS_UUID, "", ParametersType.VOLTAGE_INIT_PARAMETERS.name(), PARENT_DIRECTORY_UUID) + .header("userId", USER1) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"content\": \"new Parameters content\"}")) + .andExpect(status().isOk()); } @Test - public void testNewScriptFromFilter() throws Exception { + void testNewScriptFromFilter() throws Exception { + directoryService.expectGetElementsFilterUuid(); //GET /elements/${FILTER_UUID} + filterService.expectPostFiltersNewScript(); //POST /filters/${FILTER_UUID}/new-script?newId=00000000-0000-0000-0000-000000000000 + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + mockMvc.perform(post("/v1/explore/filters/{id}/new-script/{scriptName}?parentDirectoryUuid={parentDirectoryUuid}", - FILTER_UUID, "scriptName", PARENT_DIRECTORY_UUID) - .header("userId", USER1) - ).andExpect(status().isOk()); + FILTER_UUID, "scriptName", PARENT_DIRECTORY_UUID) + .header("userId", USER1)) + .andExpect(status().isOk()); } @Test - public void testReplaceFilterWithScript() throws Exception { - mockMvc.perform(post("/v1/explore/filters/{id}/replace-with-script", - FILTER_UUID) - .header("userId", USER1) - ).andExpect(status().isOk()); - } + void testReplaceFilterWithScript() throws Exception { + directoryService.expectGetElementsFilterUuid(); //GET /elements/${FILTER_UUID} + filterService.expectPutFiltersReplaceWithScript(); //PUT /filters/${FILTER_UUID}/replace-with-script + directoryService.expectHttpElementsFilterUuidNotificationTypeUpdateDirectory(); //POST /elements/${FILTER_UUID}/notification?type=UPDATE_DIRECTORY + expectNoMoreRestCall(); - public void deleteElement(UUID elementUUid) throws Exception { - mockMvc.perform(delete("/v1/explore/elements/{elementUuid}", - elementUUid).header("userId", USER1)) + mockMvc.perform(post("/v1/explore/filters/{id}/replace-with-script", FILTER_UUID).header("userId", USER1)) .andExpect(status().isOk()); } - public void deleteElementInvalidType(UUID elementUUid) throws Exception { - mockMvc.perform(delete("/v1/explore/elements/{elementUuid}", elementUUid) - .header("userId", USER1)) - .andExpect(status().is2xxSuccessful()); - } + @DisplayName("tests delete element") + @Nested + class ExploreTestDeleteElements { + private void deleteElement(UUID elementUUid) throws Exception { + mockMvc.perform(delete("/v1/explore/elements/{elementUuid}", elementUUid).header("userId", USER1)) + .andExpect(status().isOk()); + } - @Test - public void testDeleteElement() throws Exception { - deleteElement(FILTER_UUID); - deleteElement(PRIVATE_STUDY_UUID); - deleteElement(CONTINGENCY_LIST_UUID); - deleteElementInvalidType(INVALID_ELEMENT_UUID); - deleteElement(PARENT_DIRECTORY_UUID); - deleteElement(CASE_UUID); - deleteElement(PARAMETERS_UUID); - } + @Test + void testDeleteFilterElement() throws Exception { + directoryService.expectGetElementsFilterUuid(); //GET /elements/${FILTER_UUID} + filterService.expectDeleteFiltersFilterUuid(); //DELETE /filters/${FILTER_UUID} + directoryService.expectDeleteElementsFilterUuid(); //DELETE /elements/${FILTER_UUID} + expectNoMoreRestCall(); - @Test - public void testGetElementsMetadata() throws Exception { - mockMvc.perform(get("/v1/explore/elements/metadata?ids=" + FILTER_UUID + "," + PRIVATE_STUDY_UUID + "," + CONTINGENCY_LIST_UUID) - .header("userId", USER1) - ).andExpectAll(status().isOk()); - - ElementAttributes filter1 = new ElementAttributes(FILTER_UUID, FILTER_CONTINGENCY_LIST, FILTER, new AccessRightsAttributes(true), USER1, 0L, null, specificMetadata); - ElementAttributes filter2 = new ElementAttributes(FILTER_UUID_2, FILTER_CONTINGENCY_LIST_2, FILTER, new AccessRightsAttributes(true), USER1, 0L, null, specificMetadata2); - - mockMvc.perform(get("/v1/explore/elements/metadata?ids=" + FILTER_UUID + "," + FILTER_UUID_2 + "&equipmentTypes=&elementTypes=FILTER") - .header("userId", USER1)) - .andExpectAll( - status().isOk(), - content().string(mapper.writeValueAsString(List.of(filter1, filter2))) - ); - - mockMvc.perform(get("/v1/explore/elements/metadata?ids=" + FILTER_UUID + "," + FILTER_UUID_2 + "&equipmentTypes=GENERATOR&elementTypes=FILTER") - .header("userId", USER1)) - .andExpectAll( - status().isOk(), - content().string(mapper.writeValueAsString(List.of())) - ); - - mockMvc.perform(get("/v1/explore/elements/metadata?ids=" + FILTER_UUID + "," + FILTER_UUID_2 + "&equipmentTypes=LINE&elementTypes=FILTER") - .header("userId", USER1)) - .andExpectAll( - status().isOk(), - content().string(mapper.writeValueAsString(List.of(filter2))) - ); - } + deleteElement(FILTER_UUID); + } - @Test - public void testDuplicateCase() throws Exception { - mockMvc.perform(post("/v1/explore/cases?duplicateFrom={parentCaseUuid}&caseName={caseName}&description={description}&parentDirectoryUuid={parentDirectoryUuid}", - CASE_UUID, CASE1, "description", PARENT_DIRECTORY_UUID).header("userId", USER1)) - .andExpect(status().isOk()); - } + @Test + void testDeleteElementPrivateStudy() throws Exception { + directoryService.expectGetElementsPrivateStudyUuid(); //GET /elements/${PRIVATE_STUDY_UUID} + studyService.expectDeleteStudiesPrivateStudyUuid(); //DELETE /studies/${PRIVATE_STUDY_UUID} + directoryService.expectDeleteElementsPrivateStudyUuid(); //DELETE /elements/${PRIVATE_STUDY_UUID} + expectNoMoreRestCall(); - @Test - public void testDuplicateFilter() throws Exception { - mockMvc.perform(post("/v1/explore/filters?duplicateFrom={parentFilterId}&name={filterName}&description={description}&parentDirectoryUuid={parentDirectoryUuid}", - FILTER_UUID, FILTER1, "description", PARENT_DIRECTORY_UUID) - .header("userId", USER1)).andExpect(status().isOk()); - } + deleteElement(PRIVATE_STUDY_UUID); + } - @Test - public void testDuplicateScriptContingencyList() throws Exception { - mockMvc.perform(post("/v1/explore/script-contingency-lists?duplicateFrom={parentListId}&listName={listName}&description={description}&parentDirectoryUuid={parentDirectoryUuid}", - CONTINGENCY_LIST_UUID, STUDY1, "description", PARENT_DIRECTORY_UUID) - .header("userId", USER1)) - .andExpect(status().isOk()); - } + @Test + void testDeleteContingencyElement() throws Exception { + directoryService.expectGetElementsContingencyListUuid(); //GET /elements/${CONTINGENCY_LIST_UUID} + contingencyListService.expectDeleteContingencyListsContingencyListUuid(); //DELETE /contingency-lists/${CONTINGENCY_LIST_UUID} + directoryService.expectDeleteElementsContingencyListUuid(); //DELETE /elements/${CONTINGENCY_LIST_UUID} + expectNoMoreRestCall(); - @Test - public void testDuplicateFormContingencyList() throws Exception { - mockMvc.perform(post("/v1/explore/form-contingency-lists?duplicateFrom={parentListId}&listName={listName}&description={description}&parentDirectoryUuid={parentDirectoryUuid}", - CONTINGENCY_LIST_UUID, STUDY1, "description", PARENT_DIRECTORY_UUID) - .header("userId", USER1) - ).andExpect(status().isOk()); - } + deleteElement(CONTINGENCY_LIST_UUID); + } - @Test - public void testDuplicateIdentifierContingencyList() throws Exception { - mockMvc.perform(post("/v1/explore/identifier-contingency-lists?duplicateFrom={parentListId}&listName={listName}&description={description}&parentDirectoryUuid={parentDirectoryUuid}", - CONTINGENCY_LIST_UUID, STUDY1, "description", PARENT_DIRECTORY_UUID) - .header("userId", USER1) - ).andExpect(status().isOk()); - } + @Test + void testDeleteInvalidElement() throws Exception { + directoryService.expectGetElementsInvalidElementUuid(); //GET /elements/${INVALID_ELEMENT_UUID} + directoryService.expectDeleteElementsInvalidElementUuid(); //DELETE /elements/${INVALID_ELEMENT_UUID} + expectNoMoreRestCall(); - @Test - public void testDuplicateStudy() throws Exception { - mockMvc.perform(post("/v1/explore/studies?duplicateFrom={parentStudyUuid}&studyName={studyName}&description={description}&parentDirectoryUuid={parentDirectoryUuid}", - PUBLIC_STUDY_UUID, STUDY1, "description", PARENT_DIRECTORY_UUID) - .header("userId", USER1) - ).andExpect(status().isOk()); - } + mockMvc.perform(delete("/v1/explore/elements/{elementUuid}", INVALID_ELEMENT_UUID).header("userId", USER1)) + .andExpect(status().is2xxSuccessful()); + } - @Test - public void testCaseCreationErrorWithBadExtension() throws Exception { - try (InputStream is = new FileInputStream(ResourceUtils.getFile("classpath:" + TEST_INCORRECT_FILE))) { - MockMultipartFile mockFile = new MockMultipartFile("caseFile", TEST_INCORRECT_FILE, "text/xml", is); + @Test + void testDeleteParentDirectoryElement() throws Exception { + directoryService.expectGetElementsParentDirectoryUuid(); //GET /elements/${PARENT_DIRECTORY_UUID} + directoryService.expectGetDirectoriesParentDirectoryUuidElements(); //GET /directories/${PARENT_DIRECTORY_UUID}/elements + directoryService.expectDeleteElementsParentDirectoryUuid(); //DELETE /elements/${PARENT_DIRECTORY_UUID} + expectNoMoreRestCall(); - mockMvc.perform(multipart("/v1/explore/cases/{caseName}?description={description}&parentDirectoryUuid={parentDirectoryUuid}", - STUDY_ERROR_NAME, "description", PARENT_DIRECTORY_UUID).file(mockFile) - .header("userId", USER1) - .contentType(MediaType.MULTIPART_FORM_DATA)) - .andExpect(status().isUnprocessableEntity()); + deleteElement(PARENT_DIRECTORY_UUID); } - } - @Test - public void testChangeFilter() throws Exception { - final String filter = "{\"type\":\"CRITERIA\",\"equipmentFilterForm\":{\"equipmentType\":\"BATTERY\",\"name\":\"test bbs\",\"countries\":[\"BS\"],\"nominalVoltage\":{\"type\":\"LESS_THAN\",\"value1\":545430,\"value2\":null},\"freeProperties\":{\"region\":[\"north\"],\"totallyFree\":[\"6555\"],\"tso\":[\"ceps\"]}}}"; - final String name = "filter name"; - mockMvc.perform(put("/v1/explore/filters/{id}", - FILTER_UUID) - .contentType(APPLICATION_JSON) - .content(filter) - .param("name", name) - .header("userId", USER1) - ).andExpect(status().isOk()); - - verifyFilterOrContingencyUpdateRequests("/v1/filters/"); + @Test + void testDeleteCaseElement() throws Exception { + directoryService.expectGetElementsCaseUuid(); //GET /elements/${CASE_UUID} + caseService.expectDeleteCasesCaseUuid(); //DELETE /cases/${CASE_UUID} + directoryService.expectDeleteElementsCaseUuid(); //DELETE /elements/${CASE_UUID} + expectNoMoreRestCall(); + + deleteElement(CASE_UUID); + } + + @Test + void testDeleteParametersElement() throws Exception { + directoryService.expectGetElementsParametersUuid(); //GET /elements/${PARAMETERS_UUID} + directoryService.expectGetElementsParametersUuid(); // why? //GET /elements/${PARAMETERS_UUID} + parametersService.expectDeleteVoltageInitParametersParametersUuid(); //DELETE http://voltage_init_parameters/v1/parameters/${PARAMETERS_UUID} + directoryService.expectDeleteElementsParametersUuid(); //DELETE /elements/${PARAMETERS_UUID} + expectNoMoreRestCall(); + + deleteElement(PARAMETERS_UUID); + } } - @Test - public void testModifyScriptContingencyList() throws Exception { - final String scriptContingency = "{\"script\":\"alert(\\\"script contingency\\\")\"}"; - final String name = "script name"; - mockMvc.perform(put("/v1/explore/contingency-lists/{id}", - SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID) - .contentType(APPLICATION_JSON) - .content(scriptContingency) - .param("name", name) - .param("contingencyListType", ContingencyListType.SCRIPT.name()) - .header("userId", USER1) - ).andExpect(status().isOk()); - - verifyFilterOrContingencyUpdateRequests("/v1/script-contingency-lists"); + @DisplayName("tests get elements metadata") + @Nested + class ExploreTestGetElementsMetadata { + @Test + void testGetElementsMetadataWithoutFilter() throws Exception { + directoryService.expectGetElementsIdsFilterUuidPrivateStudyUuidContingencyListUuid(); //GET /elements?ids=${FILTER_UUID},${PRIVATE_STUDY_UUID},${CONTINGENCY_LIST_UUID} + studyService.expectGetStudiesMetadataIdsPrivateStudyUuid(); //GET /studies/metadata?ids=${PRIVATE_STUDY_UUID} + filterService.expectGetFiltersMetadataIdsFilterUuid(); //GET /filters/metadata?ids=${FILTER_UUID} + contingencyListService.expectGetContingencyListsMetadataIdsContingencyListUuid(); //GET /contingency-lists/metadata?ids=${CONTINGENCY_LIST_UUID} + expectNoMoreRestCall(); + + mockMvc.perform(get("/v1/explore/elements/metadata?ids=" + FILTER_UUID + "," + PRIVATE_STUDY_UUID + "," + CONTINGENCY_LIST_UUID) + .header("userId", USER1)) + .andExpectAll(status().isOk()); + } + + private static final ElementAttributes FILTER1 = new ElementAttributes(FILTER_UUID, FILTER_CONTINGENCY_LIST, FILTER, new AccessRightsAttributes(true), USER1, 0L, null, SPECIFIC_METADATA); + private static final ElementAttributes FILTER2 = new ElementAttributes(FILTER_UUID_2, FILTER_CONTINGENCY_LIST_2, FILTER, new AccessRightsAttributes(true), USER1, 0L, null, SPECIFIC_METADATA_2); + + @Test + void testGetElementsMetadataWithFilterNoEquipment() throws Exception { + directoryService.expectGetElementsIdsFilterUuidFilterUuid2ElementtypesFilter(); //GET /elements?ids=${FILTER_UUID},${FILTER_UUID_2}&elementTypes=FILTER + filterService.expectGetFiltersMetadataIdsFilterUuidFilterUuid2(); //GET /filters/metadata?ids=${FILTER_UUID},${FILTER_UUID_2} + expectNoMoreRestCall(); + + mockMvc.perform(get("/v1/explore/elements/metadata?ids=" + FILTER_UUID + "," + FILTER_UUID_2 + "&equipmentTypes=&elementTypes=FILTER") + .header("userId", USER1)) + .andExpectAll( + status().isOk(), + content().string(mapper.writeValueAsString(List.of(FILTER1, FILTER2))) + ); + } + + @Test + void testGetElementsMetadataWithFilterGeneratorEquipment() throws Exception { + directoryService.expectGetElementsIdsFilterUuidFilterUuid2ElementtypesFilter(); //GET /elements?ids=${FILTER_UUID},${FILTER_UUID_2}&elementTypes=FILTER + filterService.expectGetFiltersMetadataIdsFilterUuidFilterUuid2(); //GET /filters/metadata?ids=${FILTER_UUID},${FILTER_UUID_2} + expectNoMoreRestCall(); + + mockMvc.perform(get("/v1/explore/elements/metadata?ids=" + FILTER_UUID + "," + FILTER_UUID_2 + "&equipmentTypes=GENERATOR&elementTypes=FILTER") + .header("userId", USER1)) + .andExpectAll( + status().isOk(), + content().string("[]") + ); + } + + @Test + void testGetElementsMetadataWithFilterLineEquipment() throws Exception { + directoryService.expectGetElementsIdsFilterUuidFilterUuid2ElementtypesFilter(); //GET /elements?ids=${FILTER_UUID},${FILTER_UUID_2}&elementTypes=FILTER + filterService.expectGetFiltersMetadataIdsFilterUuidFilterUuid2(); //GET /filters/metadata?ids=${FILTER_UUID},${FILTER_UUID_2} + expectNoMoreRestCall(); + + mockMvc.perform(get("/v1/explore/elements/metadata?ids=" + FILTER_UUID + "," + FILTER_UUID_2 + "&equipmentTypes=LINE&elementTypes=FILTER") + .header("userId", USER1)) + .andExpectAll( + status().isOk(), + content().string(mapper.writeValueAsString(List.of(FILTER2))) + ); + } + + @Test + void testGetCaseMetadata() throws Exception { + directoryService.expectGetElementsIdsCaseUuid(); //GET /elements?ids=${CASE_UUID} + caseService.expectGetCasesMetadataIdsCaseUuid(); //GET /cases/metadata?ids=${CASE_UUID} + expectNoMoreRestCall(); + + MvcResult result = mockMvc.perform(get("/v1/explore/elements/metadata?ids=" + CASE_UUID) + .header("userId", USER1)) + .andExpect(status().isOk()) + .andReturn(); + String res = result.getResponse().getContentAsString(); + assertThat(mapper.readValue(res, new TypeReference>() { })) + .as("elementsMetadata") + .hasSize(1) //TODO replace only when assertj updated + .extracting(mapper::writeValueAsString) + .first() + .asString() + .as("caseAttributesAsString") + .isEqualTo(mapper.writeValueAsString(new ElementAttributes(CASE_UUID, "case", "CASE", new AccessRightsAttributes(true), USER1, 0L, null, CASE_SPECIFIC_METADATA))); + } } - @Test - public void testModifyFormContingencyList() throws Exception { - final String formContingency = "{\"equipmentType\":\"LINE\",\"name\":\"contingency EN update1\",\"countries1\":[\"AL\"],\"countries2\":[],\"nominalVoltage1\":{\"type\":\"EQUALITY\",\"value1\":45340,\"value2\":null},\"nominalVoltage2\":null,\"freeProperties1\":{},\"freeProperties2\":{}}"; - final String name = "form contingency name"; - mockMvc.perform(put("/v1/explore/contingency-lists/{id}", - SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID) - .contentType(APPLICATION_JSON) - .content(formContingency) - .param("name", name) - .param("contingencyListType", ContingencyListType.FORM.name()) - .header("userId", USER1) - ).andExpect(status().isOk()); - - verifyFilterOrContingencyUpdateRequests("/v1/form-contingency-lists/"); + @DisplayName("tests duplicate elements") + @Nested + class ExploreTestDuplicate { + @Test + void testDuplicateCase() throws Exception { + caseService.expectPostCasesNoIncorrectOrErrorFile(); //POST /cases?duplicateFrom=${CASE_UUID} + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/cases?duplicateFrom={parentCaseUuid}&caseName={caseName}&description={description}&parentDirectoryUuid={parentDirectoryUuid}", + CASE_UUID, CASE1, "description", PARENT_DIRECTORY_UUID) + .header("userId", USER1)) + .andExpect(status().isOk()); + } + + @Test + void testDuplicateFilter() throws Exception { + filterService.expectPostFilters(); //POST /filters?duplicateFrom=${FILTER_UUID}&id=00000000-0000-0000-0000-000000000000 + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/filters?duplicateFrom={parentFilterId}&name={filterName}&description={description}&parentDirectoryUuid={parentDirectoryUuid}", + FILTER_UUID, FILTER1, "description", PARENT_DIRECTORY_UUID) + .header("userId", USER1)) + .andExpect(status().isOk()); + } + + @Test + void testDuplicateScriptContingencyList() throws Exception { + contingencyListService.expectPostScriptContingencyLists(); //POST /script-contingency-lists?duplicateFrom=${CONTINGENCY_LIST_UUID}&id=00000000-0000-0000-0000-000000000000 + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/script-contingency-lists?duplicateFrom={parentListId}&listName={listName}&description={description}&parentDirectoryUuid={parentDirectoryUuid}", + CONTINGENCY_LIST_UUID, STUDY1, "description", PARENT_DIRECTORY_UUID) + .header("userId", USER1)) + .andExpect(status().isOk()); + } + + @Test + void testDuplicateFormContingencyList() throws Exception { + contingencyListService.expectPostFormContingencyLists(); //POST /form-contingency-lists?duplicateFrom=${CONTINGENCY_LIST_UUID}&id=00000000-0000-0000-0000-000000000000 + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/form-contingency-lists?duplicateFrom={parentListId}&listName={listName}&description={description}&parentDirectoryUuid={parentDirectoryUuid}", + CONTINGENCY_LIST_UUID, STUDY1, "description", PARENT_DIRECTORY_UUID) + .header("userId", USER1)) + .andExpect(status().isOk()); + } + + @Test + void testDuplicateIdentifierContingencyList() throws Exception { + contingencyListService.expectPostIdentifierContingencyLists(); //POST /identifier-contingency-lists?duplicateFrom=${CONTINGENCY_LIST_UUID}&id=00000000-0000-0000-0000-000000000000 + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/identifier-contingency-lists?duplicateFrom={parentListId}&listName={listName}&description={description}&parentDirectoryUuid={parentDirectoryUuid}", + CONTINGENCY_LIST_UUID, STUDY1, "description", PARENT_DIRECTORY_UUID) + .header("userId", USER1)) + .andExpect(status().isOk()); + } + + @Test + void testDuplicateStudy() throws Exception { + studyService.expectPostStudies(); //POST /studies?duplicateFrom=${PUBLIC_STUDY_UUID}&studyUuid=00000000-0000-0000-0000-000000000000 + directoryService.expectPostDirectoriesParentDirectoryUuidElements(); //POST /directories/${PARENT_DIRECTORY_UUID}/elements + expectNoMoreRestCall(); + + mockMvc.perform(post("/v1/explore/studies?duplicateFrom={parentStudyUuid}&studyName={studyName}&description={description}&parentDirectoryUuid={parentDirectoryUuid}", + PUBLIC_STUDY_UUID, STUDY1, "description", PARENT_DIRECTORY_UUID) + .header("userId", USER1)) + .andExpect(status().isOk()); + } } @Test - public void testModifyIdentifierContingencyList() throws Exception { - final String identifierContingencyList = "{\"identifierContingencyList\":{\"type\":\"identifier\",\"version\":\"1.0\",\"identifiableType\":\"LINE\",\"identifiers\":[{\"type\":\"LIST\",\"identifierList\":[{\"type\":\"ID_BASED\",\"identifier\":\"34\"},{\"type\":\"ID_BASED\",\"identifier\":\"qs\"}]}]},\"type\":\"IDENTIFIERS\"}"; - final String name = "identifier contingencyList name"; - mockMvc.perform(put("/v1/explore/contingency-lists/{id}", - SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID) - .contentType(APPLICATION_JSON) - .content(identifierContingencyList) - .param("name", name) - .param("contingencyListType", ContingencyListType.IDENTIFIERS.name()) - .header("userId", USER1) - ).andExpect(status().isOk()); - - verifyFilterOrContingencyUpdateRequests("/v1/identifier-contingency-lists/"); + void testChangeFilter() throws Exception { + filterService.expectPutFilters(); //PUT /filters/${FILTER_UUID} + directoryService.expectPutElements(); //PUT /elements/${FILTER_UUID} + expectNoMoreRestCall(); + + mockMvc.perform(put("/v1/explore/filters/{id}", FILTER_UUID) + .contentType(APPLICATION_JSON) + .content("{\"type\":\"CRITERIA\",\"equipmentFilterForm\":{\"equipmentType\":\"BATTERY\",\"name\":\"test bbs\",\"countries\":[\"BS\"],\"nominalVoltage\":{\"type\":\"LESS_THAN\",\"value1\":545430,\"value2\":null},\"freeProperties\":{\"region\":[\"north\"],\"totallyFree\":[\"6555\"],\"tso\":[\"ceps\"]}}}") + .param("name", "filter name") + .header("userId", USER1)) + .andExpect(status().isOk()); } - private void verifyFilterOrContingencyUpdateRequests(String contingencyOrFilterPath) { - var requests = TestUtils.getRequestsWithBodyDone(2, server); - assertTrue("elementAttributes updated", requests.stream().anyMatch(r -> r.getPath().contains(contingencyOrFilterPath))); - assertTrue("name updated", requests.stream().anyMatch(r -> r.getPath().contains("/v1/elements/"))); - } + @DisplayName("tests modify contingency list") + @Nested + class ExploreTestModifyContingencyList { + @Test + void testModifyScriptContingencyList() throws Exception { + contingencyListService.expectPutScriptContingencyLists(); //PUT /script-contingency-lists/${SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID} + directoryService.expectPutElements(); //PUT /elements/${SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID} + expectNoMoreRestCall(); + + mockMvc.perform(put("/v1/explore/contingency-lists/{id}", SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID) + .contentType(APPLICATION_JSON) + .content("{\"script\":\"alert(\\\"script contingency\\\")\"}") + .param("name", "script name") + .param("contingencyListType", ContingencyListType.SCRIPT.name()) + .header("userId", USER1)) + .andExpect(status().isOk()); + } - @Test - public void testGetMetadata() throws Exception { - MvcResult result = mockMvc.perform(get("/v1/explore/elements/metadata?ids=" + CASE_UUID) - .header("userId", USER1)) - .andExpect(status().isOk()) - .andReturn(); - String res = result.getResponse().getContentAsString(); - List elementsMetadata = mapper.readValue(res, new TypeReference<>() { - }); - String caseAttributesAsString = mapper.writeValueAsString(new ElementAttributes(CASE_UUID, "case", "CASE", new AccessRightsAttributes(true), USER1, 0L, null, caseSpecificMetadata)); - assertEquals(1, elementsMetadata.size()); - assertEquals(mapper.writeValueAsString(elementsMetadata.get(0)), caseAttributesAsString); + @Test + void testModifyFormContingencyList() throws Exception { + contingencyListService.expectPutFormContingencyLists(); //PUT /form-contingency-lists/${SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID} + directoryService.expectPutElements(); //PUT /elements/${SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID} + expectNoMoreRestCall(); + + mockMvc.perform(put("/v1/explore/contingency-lists/{id}", SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID) + .contentType(APPLICATION_JSON) + .content("{\"equipmentType\":\"LINE\",\"name\":\"contingency EN update1\",\"countries1\":[\"AL\"],\"countries2\":[],\"nominalVoltage1\":{\"type\":\"EQUALITY\",\"value1\":45340,\"value2\":null},\"nominalVoltage2\":null,\"freeProperties1\":{},\"freeProperties2\":{}}") + .param("name", "form contingency name") + .param("contingencyListType", ContingencyListType.FORM.name()) + .header("userId", USER1)) + .andExpect(status().isOk()); + } + + @Test + void testModifyIdentifierContingencyList() throws Exception { + contingencyListService.expectPutIdentifierContingencyLists(); //PUT /identifier-contingency-lists/${SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID} + directoryService.expectPutElements(); //PUT /elements/${SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID} + expectNoMoreRestCall(); + + mockMvc.perform(put("/v1/explore/contingency-lists/{id}", SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID) + .contentType(APPLICATION_JSON) + .content("{\"identifierContingencyList\":{\"type\":\"identifier\",\"version\":\"1.0\",\"identifiableType\":\"LINE\",\"identifiers\":[{\"type\":\"LIST\",\"identifierList\":[{\"type\":\"ID_BASED\",\"identifier\":\"34\"},{\"type\":\"ID_BASED\",\"identifier\":\"qs\"}]}]},\"type\":\"IDENTIFIERS\"}") + .param("name", "identifier contingencyList name") + .param("contingencyListType", ContingencyListType.IDENTIFIERS.name()) + .header("userId", USER1)) + .andExpect(status().isOk()); + } } } diff --git a/src/test/java/org/gridsuite/explore/server/ExploreTestExtension.java b/src/test/java/org/gridsuite/explore/server/ExploreTestExtension.java new file mode 100644 index 00000000..01cc1983 --- /dev/null +++ b/src/test/java/org/gridsuite/explore/server/ExploreTestExtension.java @@ -0,0 +1,78 @@ +package org.gridsuite.explore.server; + +import lombok.NonNull; +import org.apache.commons.lang3.ArrayUtils; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.AfterTestExecutionCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Field; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.regex.Pattern; + +import static org.gridsuite.explore.server.ExploreTest.*; +import static org.gridsuite.explore.server.services.MockRemoteServices.*; + +/** + * Extension to intercept exceptions to modify the message. + */ +@SuppressWarnings("RedundantThrows") +public class ExploreTestExtension implements AfterTestExecutionCallback, AfterEachCallback { + @Override + public void afterTestExecution(ExtensionContext context) throws Exception { + context.getExecutionException().ifPresent(this::modifyMessage); + } + + @Override + public void afterEach(ExtensionContext context) throws Exception { + context.getExecutionException().ifPresent(this::modifyMessage); + } + + @SuppressWarnings("removal") + private void modifyMessage(@NonNull final Throwable ex) { + try { + final Field detailMessage = ReflectionUtils.findField(ex.getClass(), "detailMessage", String.class); + if (System.getSecurityManager() == null) { + ReflectionUtils.makeAccessible(detailMessage); + } else { + AccessController.doPrivileged((PrivilegedAction) () -> { + ReflectionUtils.makeAccessible(detailMessage); + return null; + }); + } + ReflectionUtils.setField(detailMessage, ex, ex.getMessage() + .replaceAll(Pattern.quote(TEST_FILE), "\\${TEST_FILE}") + .replaceAll(Pattern.quote(TEST_FILE_WITH_ERRORS), "\\${TEST_FILE_WITH_ERRORS}") + .replaceAll(Pattern.quote(TEST_INCORRECT_FILE), "\\${TEST_INCORRECT_FILE}") + .replaceAll(Pattern.quote(CASE_UUID.toString()), "\\${CASE_UUID}") + .replaceAll(Pattern.quote(NON_EXISTING_CASE_UUID.toString()), "\\${NON_EXISTING_CASE_UUID}") + .replaceAll(Pattern.quote(PARENT_DIRECTORY_UUID.toString()), "\\${PARENT_DIRECTORY_UUID}") + .replaceAll(Pattern.quote(PARENT_DIRECTORY_WITH_ERROR_UUID.toString()), "\\${PARENT_DIRECTORY_WITH_ERROR_UUID}") + .replaceAll(Pattern.quote(PRIVATE_STUDY_UUID.toString()), "\\${PRIVATE_STUDY_UUID}") + .replaceAll(Pattern.quote(PUBLIC_STUDY_UUID.toString()), "\\${PUBLIC_STUDY_UUID}") + .replaceAll(Pattern.quote(FILTER_UUID.toString()), "\\${FILTER_UUID}") + .replaceAll(Pattern.quote(FILTER_UUID_2.toString()), "\\${FILTER_UUID_2}") + .replaceAll(Pattern.quote(SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID.toString()), "\\${SCRIPT_ID_BASE_FORM_CONTINGENCY_LIST_UUID}") + .replaceAll(Pattern.quote(CONTINGENCY_LIST_UUID.toString()), "\\${CONTINGENCY_LIST_UUID}") + .replaceAll(Pattern.quote(INVALID_ELEMENT_UUID.toString()), "\\${INVALID_ELEMENT_UUID}") + .replaceAll(Pattern.quote(PARAMETERS_UUID.toString()), "\\${PARAMETERS_UUID}") + .replaceAll(Pattern.quote(STUDY_ERROR_NAME), "\\${STUDY_ERROR_NAME}") + .replaceAll(Pattern.quote(STUDY1), "\\${STUDY1}") + .replaceAll(Pattern.quote(CASE1), "\\${CASE1}") + .replaceAll(Pattern.quote(USER1), "\\${USER1}") + //.replaceAll(Pattern.quote(FILTER), "\\${FILTER}") + .replaceAll(Pattern.quote(FILTER1), "\\${FILTER1}") + .replaceAll(Pattern.quote(FILTER_CONTINGENCY_LIST), "\\${FILTER_CONTINGENCY_LIST}") + .replaceAll(Pattern.quote(FILTER_CONTINGENCY_LIST_2), "\\${FILTER_CONTINGENCY_LIST_2}")); + } catch (Throwable err) { + err.printStackTrace(); + } + if (ArrayUtils.isNotEmpty(ex.getSuppressed())) { + for (final Throwable suppressed : ex.getSuppressed()) { + modifyMessage(suppressed); + } + } + } +} diff --git a/src/test/java/org/gridsuite/explore/server/TestConfig.java b/src/test/java/org/gridsuite/explore/server/TestConfig.java new file mode 100644 index 00000000..64abab90 --- /dev/null +++ b/src/test/java/org/gridsuite/explore/server/TestConfig.java @@ -0,0 +1,77 @@ +package org.gridsuite.explore.server; + +import org.gridsuite.explore.server.services.*; +import org.gridsuite.explore.server.utils.ParametersType; +import org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerAutoConfiguration; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.web.client.MockServerRestTemplateCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.web.client.RestTemplate; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * because @AutoConfigureMockRestServiceServer support only 1 restTemplate instance, we need to do it ourselves + * @see MockRestServiceServerAutoConfiguration + */ +@TestConfiguration +public class TestConfig { + @DynamicPropertySource + static void setDynamicProperties(final DynamicPropertyRegistry registry) { + registry.add("spring.cache.type", () -> "none"); + } + + @Bean + public MockServerRestTemplateCustomizer mockServerRestTemplateCustomizer() { + return new MockServerRestTemplateCustomizer(); + } + + @SuppressWarnings("OptionalGetWithoutIsPresent") + private static RestTemplate getRestTemplate(final Class clazz, final T service) throws IllegalAccessException { + final Field rtField = Arrays.stream(clazz.getDeclaredFields()).filter(f -> RestTemplate.class.equals(f.getType())).findAny().get(); + rtField.setAccessible(true); + return (RestTemplate) rtField.get(service); + } + + @Bean + public MockRestServiceServer mockRestSrvCaseService(MockServerRestTemplateCustomizer customizer, CaseService caseService) throws IllegalAccessException { + return customizer.getServer(getRestTemplate(CaseService.class, caseService)); + } + + @Bean + public MockRestServiceServer mockRestSrvContingencyListService(MockServerRestTemplateCustomizer customizer, ContingencyListService contingencyListService) throws IllegalAccessException { + return customizer.getServer(getRestTemplate(ContingencyListService.class, contingencyListService)); + } + + @Bean + public MockRestServiceServer mockRestSrvDirectoryService(MockServerRestTemplateCustomizer customizer, DirectoryService directoryService) throws IllegalAccessException { + return customizer.getServer(getRestTemplate(DirectoryService.class, directoryService)); + } + + @Bean + public MockRestServiceServer mockRestSrvFilterService(MockServerRestTemplateCustomizer customizer, FilterService filterService) throws IllegalAccessException { + return customizer.getServer(getRestTemplate(FilterService.class, filterService)); + } + + @Bean + public MockRestServiceServer mockRestSrvStudyService(MockServerRestTemplateCustomizer customizer, StudyService studyService) throws IllegalAccessException { + return customizer.getServer(getRestTemplate(StudyService.class, studyService)); + } + + @SuppressWarnings({"unchecked", "OptionalGetWithoutIsPresent"}) + @Bean + public Map mockRestSrvParametersService(MockServerRestTemplateCustomizer customizer, ParametersService parametersService) throws IllegalAccessException { + final Field rtField = Arrays.stream(ParametersService.class.getDeclaredFields()).filter(f -> Map.class.equals(f.getType())).findAny().get(); + rtField.setAccessible(true); + return ((Map) rtField.get(parametersService)).entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, + e -> customizer.getServer(e.getValue()) + )); + } +} diff --git a/src/test/java/org/gridsuite/explore/server/services/MockRemoteServices.java b/src/test/java/org/gridsuite/explore/server/services/MockRemoteServices.java new file mode 100644 index 00000000..59399ee2 --- /dev/null +++ b/src/test/java/org/gridsuite/explore/server/services/MockRemoteServices.java @@ -0,0 +1,1101 @@ +package org.gridsuite.explore.server.services; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.SneakyThrows; +import org.gridsuite.explore.server.dto.AccessRightsAttributes; +import org.gridsuite.explore.server.dto.ElementAttributes; +import org.gridsuite.explore.server.utils.ParametersType; +import org.hamcrest.Matchers; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.test.web.client.ExpectedCount; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.test.web.client.match.MockRestRequestMatchers; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.*; +import static org.springframework.test.web.client.response.MockRestResponseCreators.*; + +/** + * Host mocking classes of services/clients of this application to other services in GridSuite.
+ * It is based on the Spring mock of {@link org.springframework.web.client.RestTemplate RestTemplate}. + * @see org.gridsuite.explore.server.services + * @see org.gridsuite.explore.server.TestConfig TestConfig + * @see MockRestServiceServer + * @see org.springframework.boot.web.client.RestTemplateBuilder RestTemplateBuilder + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@SuppressWarnings({"HideUtilityClassConstructor"}) +public final class MockRemoteServices { + /* + * some notes: + * - @RestClientTest can't work because each @Service use one @RestTemplateBuilder (good for testing single component) + * - @AutoConfigureMockRestServiceServer dont work for same reason (support only one RestTemplateBuilder) + * - Multiple MockServer because need to check calls per server (don't distinct hostname) + */ + + public static final String TEST_FILE = "testCase.xiidm"; + public static final String TEST_FILE_WITH_ERRORS = "testCase_with_errors.xiidm"; + public static final String TEST_INCORRECT_FILE = "application-default.yml"; + + public static final UUID CASE_UUID = UUID.randomUUID(); + public static final UUID NON_EXISTING_CASE_UUID = UUID.randomUUID(); + public static final UUID PARENT_DIRECTORY_UUID = UUID.randomUUID(); + public static final UUID PARENT_DIRECTORY_WITH_ERROR_UUID = UUID.randomUUID(); + public static final UUID PRIVATE_STUDY_UUID = UUID.randomUUID(); + public static final UUID PUBLIC_STUDY_UUID = UUID.randomUUID(); + public static final UUID FILTER_UUID = UUID.randomUUID(); + public static final UUID FILTER_UUID_2 = UUID.randomUUID(); + public static final UUID CONTINGENCY_LIST_UUID = UUID.randomUUID(); + public static final UUID INVALID_ELEMENT_UUID = UUID.randomUUID(); + public static final UUID PARAMETERS_UUID = UUID.randomUUID(); + public static final String STUDY1 = "study1"; + public static final String USER1 = "user1"; + public static final String FILTER_CONTINGENCY_LIST = "filterContingencyList"; + public static final String FILTER_CONTINGENCY_LIST_2 = "filterContingencyList2"; + public static final String FILTER = "FILTER"; + + public static final Map SPECIFIC_METADATA = Map.of("id", FILTER_UUID); + public static final Map SPECIFIC_METADATA_2 = Map.of("equipmentType", "LINE", "id", FILTER_UUID_2); + public static final Map CASE_SPECIFIC_METADATA = Map.of( + "uuid", CASE_UUID, + "name", TEST_FILE, + "format", "XIIDM" + ); + + @AllArgsConstructor + private abstract static class AbstractMockRestService { + protected final MockRestServiceServer mockServer; + protected final ObjectMapper mapper; + + @SneakyThrows(JsonProcessingException.class) + protected final String jsonify(Object value) { + return mapper.writeValueAsString(value); + } + + protected void expectNoMoreCall(MockRestServiceServer mockServer) { + mockServer.expect(ExpectedCount.never(), anything()); + } + + public void expectNoMoreCall() { + this.expectNoMoreCall(mockServer); + } + + public void expectDeleteAnything() { + mockServer.expect(/*ExpectedCount.manyTimes(),*/ method(HttpMethod.DELETE)); + } + } + + /** + * Mock an HTTP server for case-server + * @see CaseService + * @see MockRestServiceServer + */ + @SuppressWarnings({"deprecation"}) + public static class MockCaseService extends AbstractMockRestService { + public MockCaseService(MockRestServiceServer mockServer, ObjectMapper mapper) { + super(mockServer, mapper); + } + + /** + * import file with errors
+ *
+ *
HTTP request
+ *
POST
+ *
uri = {@code /cases*}
+ *
body = {@code contains(filename=$TEST_FILE_WITH_ERRORS)}
+ *
HTTP response
+ *
status = {@code 409 Conflict}
+ *
body = {@code "invalid file"}
+ *
+ */ + public void expectPostCasesTestFileWithErrors() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo(Matchers.startsWith("/cases"))) + .andExpect(MockRestRequestMatchers.content().string(Matchers.containsString("filename=\"" + TEST_FILE_WITH_ERRORS + "\""))) + .andRespond(withStatus(HttpStatus.CONFLICT).body("invalid file")); //TODO no content-type? + } + + /** + * import file with errors + *
+ *
HTTP method
+ *
HTTP request
+ *
POST
+ *
uri = {@code /cases*}
+ *
body = {@code contains(filename=$TEST_INCORRECT_FILE)}
+ *
HTTP response
+ *
status = {@code 409 Conflict}
+ *
body = {@code "file with bad extension"}
+ *
+ */ + public void expectPostCasesTestIncorrectFile() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo(Matchers.startsWith("/cases"))) + .andExpect(MockRestRequestMatchers.content().string(Matchers.containsString("filename=\"" + TEST_INCORRECT_FILE + "\""))) + .andRespond(withStatus(HttpStatus.UNPROCESSABLE_ENTITY).body("file with bad extension")); //TODO no content-type? + } + + /** + *
+ *
HTTP request
+ *
POST
+ *
uri = {@code /cases*}
+ *
body = {@code not_contains(filename=$TEST_FILE_WITH_ERRORS) & not_contains(filename=$TEST_INCORRECT_FILE)}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPostCasesNoIncorrectOrErrorFile() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo(Matchers.startsWith("/cases"))) + .andExpect(MockRestRequestMatchers.content().string(Matchers.not(Matchers.allOf( + Matchers.containsString("filename=\"" + TEST_FILE_WITH_ERRORS + "\""), + Matchers.containsString("filename=\"" + TEST_INCORRECT_FILE + "\"") + )))) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
GET
+ *
uri = {@code /cases/metadata?ids=$CASE_UUID}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code [$CASE_SPECIFIC_METADATA]}
+ *
+ */ + public void expectGetCasesMetadataIdsCaseUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/cases/metadata?ids=" + CASE_UUID)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(jsonify(List.of(CASE_SPECIFIC_METADATA)))); + } + + /** + *
+ *
HTTP request
+ *
method = {@code DELETE}
+ *
uri = {@code /cases/$CASE_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectDeleteCasesCaseUuid() { + mockServer.expect(method(HttpMethod.DELETE)) + .andExpect(requestTo("/cases/" + CASE_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + } + + /** + * Mock an HTTP server for actions-server + * @see ContingencyListService + * @see MockRestServiceServer + */ + @SuppressWarnings({"deprecation"}) + public static class MockContingencyListService extends AbstractMockRestService { + public MockContingencyListService(MockRestServiceServer mockServer, ObjectMapper mapper) { + super(mockServer, mapper); + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /contingency-lists/metadata?ids=$CONTINGENCY_LIST_UUID}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code [ElementAttributes(...)]}
+ *
+ */ + public void expectGetContingencyListsMetadataIdsContingencyListUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/contingency-lists/metadata?ids=" + CONTINGENCY_LIST_UUID)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(jsonify(List.of(new ElementAttributes(CONTINGENCY_LIST_UUID, FILTER_CONTINGENCY_LIST, "CONTINGENCY_LIST", new AccessRightsAttributes(true), USER1, 0, null))).replace("elementUuid", "id"))); + } + + /** + *
+ *
HTTP request
+ *
method = {@code POST}
+ *
uri = {@code /script-contingency-lists?id=$PARENT_DIRECTORY_WITH_ERROR_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPostScriptContingencyListsIdParentDirectoryWithErrorUuid() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo("/script-contingency-lists?id=" + PARENT_DIRECTORY_WITH_ERROR_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withServerError()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code POST}
+ *
uri = {@code /script-contingency-lists*}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPostScriptContingencyLists() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo(Matchers.startsWith("/script-contingency-lists"))) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code POST}
+ *
uri = {@code /form-contingency-lists*}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPostFormContingencyLists() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo(Matchers.startsWith("/form-contingency-lists"))) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code POST}
+ *
uri = {@code /identifier-contingency-lists*}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPostIdentifierContingencyLists() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo(Matchers.startsWith("/identifier-contingency-lists"))) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code POST}
+ *
uri = {@code /form-contingency-lists/*\/new-script/*}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPostFormContingencyListsNewScript() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo(Matchers.matchesPattern("^/form-contingency-lists/.+/new-script[/?].*"))) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code PUT}
+ *
uri = {@code /script-contingency-lists/*}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPutScriptContingencyLists() { + mockServer.expect(method(HttpMethod.PUT)) + .andExpect(requestTo(Matchers.startsWith("/script-contingency-lists/"))) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code PUT}
+ *
uri = {@code /form-contingency-lists/*}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPutFormContingencyLists() { + mockServer.expect(method(HttpMethod.PUT)) + .andExpect(requestTo(Matchers.startsWith("/form-contingency-lists/"))) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code PUT}
+ *
uri = {@code /identifier-contingency-lists/*}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPutIdentifierContingencyLists() { + mockServer.expect(method(HttpMethod.PUT)) + .andExpect(requestTo(Matchers.startsWith("/identifier-contingency-lists/"))) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code DELETE}
+ *
uri = {@code /contingency-lists/$CONTINGENCY_LIST_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectDeleteContingencyListsContingencyListUuid() { + mockServer.expect(method(HttpMethod.DELETE)) + .andExpect(requestTo("/contingency-lists/" + CONTINGENCY_LIST_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + } + + /** + * Mock an HTTP server for directory-server + * @see DirectoryService + * @see MockRestServiceServer + */ + @SuppressWarnings({"deprecation"}) + public static class MockDirectoryService extends AbstractMockRestService { + public MockDirectoryService(MockRestServiceServer mockServer, ObjectMapper mapper) { + super(mockServer, mapper); + } + + private final String privateStudyAttributesAsString = jsonify(new ElementAttributes(PRIVATE_STUDY_UUID, STUDY1, "STUDY", new AccessRightsAttributes(true), USER1, 0, null)); + private final String formContingencyListAttributesAsString = jsonify(new ElementAttributes(CONTINGENCY_LIST_UUID, FILTER_CONTINGENCY_LIST, "CONTINGENCY_LIST", new AccessRightsAttributes(true), USER1, 0, null)); + private final String filterAttributesAsString = jsonify(new ElementAttributes(FILTER_UUID, FILTER_CONTINGENCY_LIST, FILTER, new AccessRightsAttributes(true), USER1, 0, null)); + private final String caseElementAttributesAsString = jsonify(new ElementAttributes(CASE_UUID, "case", "CASE", new AccessRightsAttributes(true), USER1, 0L, null)); + + /** + *
+ *
HTTP request
+ *
method = {@code POST}
+ *
uri = {@code /directories/$PARENT_DIRECTORY_UUID/elements}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code $privateStudyAttributesAsString}
+ *
+ */ + public void expectPostDirectoriesParentDirectoryUuidElements() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo("/directories/" + PARENT_DIRECTORY_UUID + "/elements")) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(privateStudyAttributesAsString)); + } + + /** + *
+ *
HTTP request
+ *
method = {@code POST}
+ *
uri = {@code /directories/$PARENT_DIRECTORY_WITH_ERROR_UUID/elements}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 500 Internal Server Error}
+ *
+ */ + public void expectPostDirectoriesParentDirectoryWithErrorUuidElements() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo("/directories/" + PARENT_DIRECTORY_WITH_ERROR_UUID + "/elements")) + .andExpect(header("userId", USER1)) + .andRespond(withServerError()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /elements/$CONTINGENCY_LIST_UUID}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code $formContingencyListAttributesAsString}
+ *
+ */ + public void expectGetElementsContingencyListUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/elements/" + CONTINGENCY_LIST_UUID)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(formContingencyListAttributesAsString)); + } + + /** + *
+ *
HTTP request
+ *
uri = {@code /elements/$CONTINGENCY_LIST_UUID/notification?type=UPDATE_DIRECTORY}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code $formContingencyListAttributesAsString}
+ *
+ */ + public void expectHttpElementsContingencyListUuidNotificationTypeUpdateDirectory() { + //TODO missing method + mockServer.expect(requestTo("/elements/" + CONTINGENCY_LIST_UUID + "/notification?type=UPDATE_DIRECTORY")) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(formContingencyListAttributesAsString)); + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /elements/$PARAMETERS_UUID}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code [ElementAttributes(...)]}
+ *
+ */ + public void expectGetElementsParametersUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/elements/" + PARAMETERS_UUID)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(jsonify(new ElementAttributes(PARAMETERS_UUID, "voltageInitParametersName", ParametersType.VOLTAGE_INIT_PARAMETERS.name(), new AccessRightsAttributes(true), USER1, 0, null)))); + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /elements/$FILTER_UUID}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code $filterAttributesAsString}
+ *
+ */ + public void expectGetElementsFilterUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/elements/" + FILTER_UUID)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(filterAttributesAsString)); + } + + /** + *
+ *
HTTP request
+ *
uri = {@code /elements/$FILTER_UUID/notification?type=UPDATE_DIRECTORY}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code $filterAttributesAsString}
+ *
+ */ + public void expectHttpElementsFilterUuidNotificationTypeUpdateDirectory() { + //TODO missing method + mockServer.expect(requestTo("/elements/" + FILTER_UUID + "/notification?type=UPDATE_DIRECTORY")) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(filterAttributesAsString)); + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /elements/$CASE_UUID}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code $caseElementAttributesAsString}
+ *
+ */ + public void expectGetElementsCaseUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/elements/" + CASE_UUID)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(caseElementAttributesAsString)); + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /elements/$PRIVATE_STUDY_UUID}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code $privateStudyAttributesAsString}
+ *
+ */ + public void expectGetElementsPrivateStudyUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/elements/" + PRIVATE_STUDY_UUID)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(privateStudyAttributesAsString)); + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /elements/$PUBLIC_STUDY_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code [ElementAttributes(...)]}
+ *
+ */ + public void expectGetElementsPublicStudyUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/elements/" + PUBLIC_STUDY_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(jsonify(new ElementAttributes(PUBLIC_STUDY_UUID, STUDY1, "STUDY", new AccessRightsAttributes(false), USER1, 0, null)))); + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /elements?ids=$FILTER_UUID,$FILTER_UUID_2&elementTypes=FILTER}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code [$filterAttributesAsString,ElementAttributes(...)]}
+ *
+ */ + public void expectGetElementsIdsFilterUuidFilterUuid2ElementtypesFilter() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/elements?ids=" + FILTER_UUID + "," + FILTER_UUID_2 + "&elementTypes=FILTER")) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body("[" + filterAttributesAsString + "," + jsonify(new ElementAttributes(FILTER_UUID_2, FILTER_CONTINGENCY_LIST_2, FILTER, new AccessRightsAttributes(true), USER1, 0, null)) + "]")); + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /elements?ids=$CASE_UUID}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code [$caseElementAttributesAsString]}
+ *
+ */ + public void expectGetElementsIdsCaseUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/elements?ids=" + CASE_UUID)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body("[" + caseElementAttributesAsString + "]")); + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /elements?ids=$FILTER_UUID,$PRIVATE_STUDY_UUID,$CONTINGENCY_LIST_UUID}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code [$filterAttributesAsString,$privateStudyAttributesAsString,$formContingencyListAttributesAsString]}
+ *
+ */ + public void expectGetElementsIdsFilterUuidPrivateStudyUuidContingencyListUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/elements?ids=" + FILTER_UUID + "," + PRIVATE_STUDY_UUID + "," + CONTINGENCY_LIST_UUID)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body("[" + filterAttributesAsString + "," + privateStudyAttributesAsString + "," + formContingencyListAttributesAsString + "]")); + } + + /** + *
+ *
HTTP request
+ *
method = {@code PUT}
+ *
uri = {@code /elements/}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
+ */ + public void expectPutElements() { + mockServer.expect(method(HttpMethod.PUT)) + .andExpect(requestTo(Matchers.startsWith("/elements/"))) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8)); //TODO missing body content + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /elements/$INVALID_ELEMENT_UUID}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code {...ElementAttributes(...)}}
+ *
+ */ + public void expectGetElementsInvalidElementUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/elements/" + INVALID_ELEMENT_UUID)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(jsonify(new ElementAttributes(INVALID_ELEMENT_UUID, "invalidElementName", "INVALID", new AccessRightsAttributes(false), USER1, 0, null)))); + } + + /** + *
+ *
HTTP request
+ *
method = {@code DELGETETE}
+ *
uri = {@code /directories/$PARENT_DIRECTORY_UUID/elements}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
+ */ + public void expectGetDirectoriesParentDirectoryUuidElements() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/directories/" + PARENT_DIRECTORY_UUID + "/elements")) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8)); //TODO missing body content + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /elements/$PARENT_DIRECTORY_UUID}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code {...ElementAttributes(...)}}
+ *
+ */ + public void expectGetElementsParentDirectoryUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/elements/" + PARENT_DIRECTORY_UUID)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(jsonify(new ElementAttributes(PARENT_DIRECTORY_UUID, "directory", "DIRECTORY", new AccessRightsAttributes(true), USER1, 0, null)))); + } + + /** + *
+ *
HTTP request
+ *
method = {@code DELETE}
+ *
uri = {@code /elements/$INVALID_ELEMENT_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectDeleteElementsInvalidElementUuid() { + mockServer.expect(method(HttpMethod.DELETE)) + .andExpect(requestTo("/elements/" + INVALID_ELEMENT_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code DELETE}
+ *
uri = {@code /elements/$PRIVATE_STUDY_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectDeleteElementsPrivateStudyUuid() { + mockServer.expect(method(HttpMethod.DELETE)) + .andExpect(requestTo("/elements/" + PRIVATE_STUDY_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code DELETE}
+ *
uri = {@code /elements/$FILTER_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectDeleteElementsFilterUuid() { + mockServer.expect(method(HttpMethod.DELETE)) + .andExpect(requestTo("/elements/" + FILTER_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code DELETE}
+ *
uri = {@code /elements/$CONTINGENCY_LIST_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectDeleteElementsContingencyListUuid() { + mockServer.expect(method(HttpMethod.DELETE)) + .andExpect(requestTo("/elements/" + CONTINGENCY_LIST_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code DELETE}
+ *
uri = {@code /elements/$PARENT_DIRECTORY_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectDeleteElementsParentDirectoryUuid() { + mockServer.expect(method(HttpMethod.DELETE)) + .andExpect(requestTo("/elements/" + PARENT_DIRECTORY_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code DELETE}
+ *
uri = {@code /elements/$CASE_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectDeleteElementsCaseUuid() { + mockServer.expect(method(HttpMethod.DELETE)) + .andExpect(requestTo("/elements/" + CASE_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code DELETE}
+ *
uri = {@code /elements/$PARAMETERS_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectDeleteElementsParametersUuid() { + mockServer.expect(method(HttpMethod.DELETE)) + .andExpect(requestTo("/elements/" + PARAMETERS_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + } + + /** + * Mock an HTTP server for filter-server + * @see FilterService + * @see MockRestServiceServer + */ + @SuppressWarnings({"deprecation"}) + public static class MockFilterService extends AbstractMockRestService { + public MockFilterService(MockRestServiceServer mockServer, ObjectMapper mapper) { + super(mockServer, mapper); + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /filters/metadata?ids=$FILTER_UUID,$FILTER_UUID_2}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code [$SPECIFIC_METADATA),$SPECIFIC_METADATA_2]}
+ *
+ */ + public void expectGetFiltersMetadataIdsFilterUuidFilterUuid2() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/filters/metadata?ids=" + FILTER_UUID + "," + FILTER_UUID_2)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body("[" + jsonify(SPECIFIC_METADATA) + "," + jsonify(SPECIFIC_METADATA_2) + "]")); + } + + /** + *
+ *
HTTP request
+ *
method = {@code POST}
+ *
uri = {@code /filters/*\/new-script*}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPostFiltersNewScript() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo(Matchers.matchesPattern("^/filters/.+/new-script.*"))) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code POST}
+ *
uri = {@code /filters*}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPostFilters() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo(Matchers.startsWith("/filters"))) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code POST}
+ *
uri = {@code /filters?id=*}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPostFiltersIdAny() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo(Matchers.startsWith("/filters?id="))) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code PUT}
+ *
uri = {@code /filters/*\/replace-with-script}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPutFiltersReplaceWithScript() { + mockServer.expect(method(HttpMethod.PUT)) + .andExpect(requestTo(Matchers.matchesPattern("^/filters/.+/replace-with-script"))) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code PUT}
+ *
uri = {@code /filters/*}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPutFilters() { + mockServer.expect(method(HttpMethod.PUT)) + .andExpect(requestTo(Matchers.startsWith("/filters/"))) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /filters/metadata?ids=$FILTER_UUID}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code [ElementAttributes(...)]}
+ *
+ */ + public void expectGetFiltersMetadataIdsFilterUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/filters/metadata?ids=" + FILTER_UUID)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(jsonify(List.of(new ElementAttributes(FILTER_UUID, FILTER_CONTINGENCY_LIST, FILTER, new AccessRightsAttributes(true), USER1, 0, null))).replace("elementUuid", "id"))); + } + + /** + *
+ *
HTTP request
+ *
method = {@code DELETE}
+ *
uri = {@code /filters/$FILTER_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectDeleteFiltersFilterUuid() { + mockServer.expect(method(HttpMethod.DELETE)) + .andExpect(requestTo("/filters/" + FILTER_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + } + + /** + * Mock an HTTP server for study-server + * @see StudyService + * @see MockRestServiceServer + */ + @SuppressWarnings({"deprecation"}) + public static class MockStudyService extends AbstractMockRestService { + public MockStudyService(MockRestServiceServer mockServer, ObjectMapper mapper) { + super(mockServer, mapper); + } + + /** + *
+ *
HTTP request
+ *
method = {@code POST}
+ *
uri = {@code /studies/cases/$NON_EXISTING_CASE_UUID(/*)?}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 404 Not Found}
+ *
+ */ + public void expectPostStudiesCasesNonExistingCaseUuid() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo(Matchers.startsWith("/studies/cases/" + NON_EXISTING_CASE_UUID))) + .andExpect(header("userId", USER1)) + .andRespond(withStatus(HttpStatus.NOT_FOUND)); + } + + /** + * import file with errors + *
+ *
HTTP request
+ *
method = {@code POST}
+ *
uri = {@code /studies*}
+ *
header: userId = {@code $USER1}
+ *
body = {@code contains(filename=$TEST_FILE_WITH_ERRORS)}
+ *
HTTP response
+ *
status = {@code 409 Conflict}
+ *
+ */ + public void expectPostStudiesTestFileWithErrors() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo(Matchers.startsWith("/studies"))) + .andExpect(header("userId", USER1)) + .andExpect(MockRestRequestMatchers.content().string(Matchers.containsString("filename=\"" + TEST_FILE_WITH_ERRORS + "\""))) + .andRespond(withStatus(HttpStatus.CONFLICT)); + } + + /** + *
+ *
HTTP request
+ *
method = {@code POST}
+ *
uri = {@code /studies*}
+ *
header: userId = {@code $USER1}
+ *
body = {@code not_contains(filename=$TEST_FILE_WITH_ERRORS)}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectPostStudies() { + mockServer.expect(method(HttpMethod.POST)) + .andExpect(requestTo(Matchers.startsWith("/studies"))) + .andExpect(header("userId", USER1)) + .andExpect(MockRestRequestMatchers.content().string(Matchers.not(Matchers.containsString("filename=\"" + TEST_FILE_WITH_ERRORS + "\"")))) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code GET}
+ *
uri = {@code /studies/metadata?ids=$PRIVATE_STUDY_UUID}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
header: content-type = {@code application/json;charset=UTF-8}
+ *
body = {@code [ElementAttributes(...)]}
+ *
+ */ + public void expectGetStudiesMetadataIdsPrivateStudyUuid() { + mockServer.expect(method(HttpMethod.GET)) + .andExpect(requestTo("/studies/metadata?ids=" + PRIVATE_STUDY_UUID)) + .andRespond(withSuccess().contentType(APPLICATION_JSON_UTF8).body(jsonify(List.of(new ElementAttributes(PRIVATE_STUDY_UUID, STUDY1, "STUDY", new AccessRightsAttributes(true), USER1, 0, null))).replace("elementUuid", "id"))); + } + + /** + *
+ *
HTTP request
+ *
method = {@code DELETE}
+ *
uri = {@code /studies/$PRIVATE_STUDY_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectDeleteStudiesPrivateStudyUuid() { + mockServer.expect(method(HttpMethod.DELETE)) + .andExpect(requestTo("/studies/" + PRIVATE_STUDY_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + } + + public static class MockParametersService extends AbstractMockRestService { + private final Map mockServers; + + public MockParametersService(Map mockServers, ObjectMapper mapper) { + super(null, mapper); + this.mockServers = mockServers; + } + + @Override + public void expectNoMoreCall() { + mockServers.values().forEach(this::expectNoMoreCall); + } + + /** + *
+ *
HTTP request
+ *
uri = {@code http://voltage_init_parameters/parameters/*}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectHttpVoltageInitAny() { + //TODO missing method + mockServers.get(ParametersType.VOLTAGE_INIT_PARAMETERS) + .expect(requestTo(Matchers.startsWith("http://voltage_init_parameters/v1/parameters"))) + .andRespond(withSuccess()); + } + + /** + *
+ *
HTTP request
+ *
method = {@code DELETE}
+ *
uri = {@code http://voltage_init_parameters/parameters/$PARAMETERS_UUID}
+ *
header: userId = {@code $USER1}
+ *
HTTP response
+ *
status = {@code 200 OK}
+ *
+ */ + public void expectDeleteVoltageInitParametersParametersUuid() { + mockServers.get(ParametersType.VOLTAGE_INIT_PARAMETERS) + .expect(method(HttpMethod.DELETE)) + .andExpect(requestTo("http://voltage_init_parameters/v1/parameters/" + PARAMETERS_UUID)) + .andExpect(header("userId", USER1)) + .andRespond(withSuccess()); + } + } +} diff --git a/src/test/java/org/gridsuite/explore/server/utils/TestUtils.java b/src/test/java/org/gridsuite/explore/server/utils/TestUtils.java deleted file mode 100644 index 5be6521e..00000000 --- a/src/test/java/org/gridsuite/explore/server/utils/TestUtils.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2022, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package org.gridsuite.explore.server.utils; - -import com.powsybl.commons.exceptions.UncheckedInterruptedException; -import okhttp3.mockwebserver.MockWebServer; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -/** - * @author AJELLAL Ali - */ -public final class TestUtils { - - private static final long TIMEOUT = 100; - - private TestUtils() { - - } - - public static Set getRequestsWithBodyDone(int n, MockWebServer server) throws UncheckedInterruptedException { - return IntStream.range(0, n).mapToObj(i -> { - try { - var request = server.takeRequest(TIMEOUT, TimeUnit.MILLISECONDS); - if (request == null) { - throw new AssertionError("Expected " + n + " requests, got only " + i); - } - return new RequestWithBody(request.getPath(), request.getBody().readUtf8()); - } catch (InterruptedException e) { - throw new UncheckedInterruptedException(e); - } - }).collect(Collectors.toSet()); - } -}