From 99b86a342bb373a0c17a27be9d8882d95ce26858 Mon Sep 17 00:00:00 2001 From: Ayoub LABIDI Date: Fri, 14 Nov 2025 02:41:37 +0100 Subject: [PATCH] Add NAD config management Signed-off-by: Ayoub LABIDI --- .../study/server/StudyException.java | 4 +- .../server/controller/StudyController.java | 29 ++ .../study/server/repository/StudyEntity.java | 8 + .../service/DiagramGridLayoutService.java | 4 +- .../server/service/NadConfigService.java | 81 ++++++ .../service/SingleLineDiagramService.java | 21 +- .../study/server/service/StudyService.java | 43 +++ .../changesets/changelog_20251113T131808Z.xml | 14 + .../db/changelog/db.changelog-master.yaml | 3 + .../gridsuite/study/server/NadConfigTest.java | 256 ++++++++++++++++++ .../StudyServiceCreateGridLayoutTest.java | 2 +- 11 files changed, 459 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/gridsuite/study/server/service/NadConfigService.java create mode 100644 src/main/resources/db/changelog/changesets/changelog_20251113T131808Z.xml create mode 100644 src/test/java/org/gridsuite/study/server/NadConfigTest.java diff --git a/src/main/java/org/gridsuite/study/server/StudyException.java b/src/main/java/org/gridsuite/study/server/StudyException.java index fe2684501..e97214a31 100644 --- a/src/main/java/org/gridsuite/study/server/StudyException.java +++ b/src/main/java/org/gridsuite/study/server/StudyException.java @@ -161,7 +161,9 @@ public enum Type { CREATE_DIAGRAM_GRID_LAYOUT_FAILED, DUPLICATE_DIAGRAM_GRID_LAYOUT_FAILED, TOO_MANY_NAD_CONFIGS, - TOO_MANY_MAP_CARDS + TOO_MANY_MAP_CARDS, + SAVE_NAD_CONFIG_FAILED, + DELETE_NAD_CONFIG_FAILED, } private final Type type; diff --git a/src/main/java/org/gridsuite/study/server/controller/StudyController.java b/src/main/java/org/gridsuite/study/server/controller/StudyController.java index 19648a426..744cda4bb 100644 --- a/src/main/java/org/gridsuite/study/server/controller/StudyController.java +++ b/src/main/java/org/gridsuite/study/server/controller/StudyController.java @@ -25,6 +25,7 @@ import org.gridsuite.study.server.dto.*; import org.gridsuite.study.server.dto.computation.LoadFlowComputationInfos; import org.gridsuite.study.server.dto.diagramgridlayout.DiagramGridLayout; +import org.gridsuite.study.server.dto.diagramgridlayout.nad.NadConfigInfos; import org.gridsuite.study.server.dto.dynamicmapping.MappingInfos; import org.gridsuite.study.server.dto.dynamicmapping.ModelInfos; import org.gridsuite.study.server.dto.dynamicsecurityanalysis.DynamicSecurityAnalysisStatus; @@ -2522,4 +2523,32 @@ public ResponseEntity updateSpreadsheetParameters(@PathVariable("studyUuid @RequestBody final SpreadsheetParameters spreadsheetParameters) { return (this.studyService.updateSpreadsheetParameters(studyUuid, spreadsheetParameters) ? ResponseEntity.noContent() : ResponseEntity.notFound()).build(); } + + @PostMapping(value = "/studies/{studyUuid}/network-area-diagrams/configs", consumes = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Save NAD config") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "NAD config is saved"), + @ApiResponse(responseCode = "404", description = "Study does not exist") + }) + public ResponseEntity saveNadConfig( + @PathVariable("studyUuid") UUID studyUuid, + @RequestBody NadConfigInfos nadConfigData) { + studyService.assertIsStudyExist(studyUuid); + UUID savedUuid = studyService.saveNadConfig(studyUuid, nadConfigData); + return ResponseEntity.ok().body(savedUuid); + } + + @DeleteMapping(value = "/studies/{studyUuid}/network-area-diagrams/configs/{nadConfigUuid}") + @Operation(summary = "Delete NAD config") + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "NAD config is deleted"), + @ApiResponse(responseCode = "404", description = "Study does not exist") + }) + public ResponseEntity deleteNadConfig( + @PathVariable("studyUuid") UUID studyUuid, + @PathVariable("nadConfigUuid") UUID nadConfigUuid) { + studyService.assertIsStudyExist(studyUuid); + studyService.deleteNadConfig(studyUuid, nadConfigUuid); + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/org/gridsuite/study/server/repository/StudyEntity.java b/src/main/java/org/gridsuite/study/server/repository/StudyEntity.java index a239468a5..7e269aa9b 100644 --- a/src/main/java/org/gridsuite/study/server/repository/StudyEntity.java +++ b/src/main/java/org/gridsuite/study/server/repository/StudyEntity.java @@ -120,6 +120,14 @@ public class StudyEntity extends AbstractManuallyAssignedIdentifierEntity )) private List nodeAliases; + @ElementCollection + @CollectionTable(name = "StudyNadConfigs", foreignKey = @ForeignKey( + name = "study_nad_configs_fk" + )) + @Column(name = "nad_config_uuid") + @Builder.Default + private List nadConfigsUuids = new ArrayList<>(); + @Column(name = "mono_root", columnDefinition = "boolean default true") private boolean monoRoot; diff --git a/src/main/java/org/gridsuite/study/server/service/DiagramGridLayoutService.java b/src/main/java/org/gridsuite/study/server/service/DiagramGridLayoutService.java index df9e09935..b9e700de6 100644 --- a/src/main/java/org/gridsuite/study/server/service/DiagramGridLayoutService.java +++ b/src/main/java/org/gridsuite/study/server/service/DiagramGridLayoutService.java @@ -135,7 +135,7 @@ private List extractNadConfigUuids(DiagramGridLayout layout) { private void cleanupOldNadConfigs(List oldNadConfigUuidsToDelete) { if (!oldNadConfigUuidsToDelete.isEmpty()) { try { - singleLineDiagramService.deleteMultipleDiagramConfigs(oldNadConfigUuidsToDelete); + singleLineDiagramService.deleteDiagramConfigs(oldNadConfigUuidsToDelete); } catch (Exception e) { LOGGER.error("Could not clean up old NAD configs: " + oldNadConfigUuidsToDelete, e); } @@ -213,7 +213,7 @@ private DiagramGridLayout processNADLayoutDetails(DiagramGridLayout diagramGridL // Batch create all NAD configs if any exist if (!nadConfigsToCreate.isEmpty()) { - singleLineDiagramService.createMultipleDiagramConfigs(nadConfigsToCreate); + singleLineDiagramService.createDiagramConfigs(nadConfigsToCreate); } return DiagramGridLayout.builder() diff --git a/src/main/java/org/gridsuite/study/server/service/NadConfigService.java b/src/main/java/org/gridsuite/study/server/service/NadConfigService.java new file mode 100644 index 000000000..9ef8b31e3 --- /dev/null +++ b/src/main/java/org/gridsuite/study/server/service/NadConfigService.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2025, 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.study.server.service; + +import lombok.RequiredArgsConstructor; +import org.gridsuite.study.server.StudyException; +import org.gridsuite.study.server.dto.diagramgridlayout.nad.NadConfigInfos; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.UUID; + +import static org.gridsuite.study.server.StudyException.Type.DELETE_NAD_CONFIG_FAILED; +import static org.gridsuite.study.server.StudyException.Type.SAVE_NAD_CONFIG_FAILED; + +/** + * @author Ayoub Labidi + */ +@Service +@RequiredArgsConstructor +public class NadConfigService { + + private static final Logger LOGGER = LoggerFactory.getLogger(NadConfigService.class); + + private final SingleLineDiagramService singleLineDiagramService; + + public UUID saveNadConfig(NadConfigInfos nadConfigInfos) { + + UUID configUuid = nadConfigInfos.getId(); + + if (configUuid == null) { + // Create new config + UUID newUuid = UUID.randomUUID(); + nadConfigInfos.setId(newUuid); + try { + singleLineDiagramService.createDiagramConfigs(List.of(nadConfigInfos)); + } catch (Exception e) { + throw new StudyException(SAVE_NAD_CONFIG_FAILED, "Could not create NAD config: " + newUuid); + } + return newUuid; + } else { + // Update existing config + try { + singleLineDiagramService.updateNadConfig(nadConfigInfos); + } catch (Exception e) { + throw new StudyException(SAVE_NAD_CONFIG_FAILED, "Could not update NAD config: " + configUuid); + } + return configUuid; + } + } + + public void deleteNadConfig(UUID configUuid) { + if (configUuid == null) { + return; + } + + try { + singleLineDiagramService.deleteDiagramConfigs(List.of(configUuid)); + } catch (Exception e) { + throw new StudyException(DELETE_NAD_CONFIG_FAILED, "Could not delete NAD config: " + configUuid); + } + } + + public void deleteNadConfigs(List nadConfigUuids) { + if (nadConfigUuids == null || nadConfigUuids.isEmpty()) { + return; + } + + try { + singleLineDiagramService.deleteDiagramConfigs(nadConfigUuids); + } catch (Exception e) { + LOGGER.error("Could not delete NAD configs: {}", nadConfigUuids, e); + } + } +} diff --git a/src/main/java/org/gridsuite/study/server/service/SingleLineDiagramService.java b/src/main/java/org/gridsuite/study/server/service/SingleLineDiagramService.java index 7eeea0cab..c1ef6d40e 100644 --- a/src/main/java/org/gridsuite/study/server/service/SingleLineDiagramService.java +++ b/src/main/java/org/gridsuite/study/server/service/SingleLineDiagramService.java @@ -221,7 +221,7 @@ public String generateNetworkAreaDiagram(UUID networkUuid, String variantId, Map } } - public void createMultipleDiagramConfigs(List nadConfigs) { + public void createDiagramConfigs(List nadConfigs) { var path = UriComponentsBuilder .fromPath(DELIMITER + SINGLE_LINE_DIAGRAM_API_VERSION + "/network-area-diagram/configs") .buildAndExpand() @@ -235,7 +235,7 @@ public void createMultipleDiagramConfigs(List nadConfigs) { restTemplate.exchange(singleLineDiagramServerBaseUri + path, HttpMethod.POST, httpEntity, Void.class); } - public void deleteMultipleDiagramConfigs(List configUuids) { + public void deleteDiagramConfigs(List configUuids) { var path = UriComponentsBuilder .fromPath(DELIMITER + SINGLE_LINE_DIAGRAM_API_VERSION + "/network-area-diagram/configs") .buildAndExpand() @@ -282,6 +282,23 @@ public UUID duplicateNadConfig(UUID sourceNadConfigUuid) { } } + public void updateNadConfig(NadConfigInfos nadConfigInfos) { + Objects.requireNonNull(nadConfigInfos); + Objects.requireNonNull(nadConfigInfos.getId()); + + var path = UriComponentsBuilder + .fromPath(DELIMITER + SINGLE_LINE_DIAGRAM_API_VERSION + "/network-area-diagram/config/{configUuid}") + .buildAndExpand(nadConfigInfos.getId()) + .toUriString(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity httpEntity = new HttpEntity<>(nadConfigInfos, headers); + + restTemplate.exchange(singleLineDiagramServerBaseUri + path, HttpMethod.PUT, httpEntity, Void.class); + } + public void createNadPositionsConfigFromCsv(MultipartFile file) { var path = UriComponentsBuilder.fromPath(DELIMITER + SINGLE_LINE_DIAGRAM_API_VERSION + "/network-area-diagram/config/positions").buildAndExpand() diff --git a/src/main/java/org/gridsuite/study/server/service/StudyService.java b/src/main/java/org/gridsuite/study/server/service/StudyService.java index e2a274b4f..d0deea44d 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -22,6 +22,7 @@ import org.gridsuite.study.server.dto.InvalidateNodeTreeParameters.InvalidationMode; import org.gridsuite.study.server.dto.caseimport.CaseImportAction; import org.gridsuite.study.server.dto.diagramgridlayout.DiagramGridLayout; +import org.gridsuite.study.server.dto.diagramgridlayout.nad.NadConfigInfos; import org.gridsuite.study.server.dto.dynamicmapping.MappingInfos; import org.gridsuite.study.server.dto.dynamicmapping.ModelInfos; import org.gridsuite.study.server.dto.dynamicsimulation.DynamicSimulationParametersInfos; @@ -129,6 +130,7 @@ public class StudyService { private final DynamicSimulationEventService dynamicSimulationEventService; private final StudyConfigService studyConfigService; private final DiagramGridLayoutService diagramGridLayoutService; + private final NadConfigService nadConfigService; private final FilterService filterService; private final ActionsService actionsService; private final CaseService caseService; @@ -193,6 +195,7 @@ public StudyService( DynamicSimulationEventService dynamicSimulationEventService, StudyConfigService studyConfigService, DiagramGridLayoutService diagramGridLayoutService, + NadConfigService nadConfigService, FilterService filterService, StateEstimationService stateEstimationService, PccMinService pccMinService, @@ -229,6 +232,7 @@ public StudyService( this.dynamicSimulationEventService = dynamicSimulationEventService; this.studyConfigService = studyConfigService; this.diagramGridLayoutService = diagramGridLayoutService; + this.nadConfigService = nadConfigService; this.filterService = filterService; this.stateEstimationService = stateEstimationService; this.pccMinService = pccMinService; @@ -544,6 +548,7 @@ private Optional doDeleteStudyIfNotCreationInProgress(UUID stu removeStateEstimationParameters(s.getStateEstimationParametersUuid()); removeSpreadsheetConfigCollection(s.getSpreadsheetConfigCollectionUuid()); removeDiagramGridLayout(s.getDiagramGridLayoutUuid()); + removeNadConfigs(s.getNadConfigsUuids()); }); deleteStudyInfos = new DeleteStudyInfos(rootNetworkInfos, modificationGroupUuids); } else { @@ -1463,6 +1468,44 @@ public String generateNetworkAreaDiagram(UUID nodeUuid, UUID rootNetworkUuid, Ma } } + @Transactional + public UUID saveNadConfig(UUID studyUuid, NadConfigInfos nadConfig) { + StudyEntity studyEntity = studyRepository.findById(studyUuid).orElseThrow(() -> new StudyException(STUDY_NOT_FOUND)); + + UUID resultUuid = nadConfigService.saveNadConfig(nadConfig); + + List nadConfigs = studyEntity.getNadConfigsUuids(); + + if (!nadConfigs.contains(resultUuid)) { + nadConfigs.add(resultUuid); + studyRepository.save(studyEntity); + } + + return resultUuid; + } + + @Transactional + public void deleteNadConfig(UUID studyUuid, UUID nadConfigUuid) { + StudyEntity studyEntity = studyRepository.findById(studyUuid).orElseThrow(() -> new StudyException(STUDY_NOT_FOUND)); + + nadConfigService.deleteNadConfig(nadConfigUuid); + + List nadConfigs = studyEntity.getNadConfigsUuids(); + if (nadConfigs.remove(nadConfigUuid)) { + studyRepository.save(studyEntity); + } + } + + private void removeNadConfigs(List nadConfigUuids) { + if (nadConfigUuids != null && !nadConfigUuids.isEmpty()) { + try { + nadConfigService.deleteNadConfigs(nadConfigUuids); + } catch (Exception e) { + LOGGER.error("Could not remove NAD configs with uuids:" + nadConfigUuids, e); + } + } + } + private void invalidateLoadFlowStatusOnAllNodes(UUID studyUuid) { loadflowService.invalidateLoadFlowStatus(rootNetworkNodeInfoService.getComputationResultUuids(studyUuid, LOAD_FLOW)); } diff --git a/src/main/resources/db/changelog/changesets/changelog_20251113T131808Z.xml b/src/main/resources/db/changelog/changesets/changelog_20251113T131808Z.xml new file mode 100644 index 000000000..158ac62a8 --- /dev/null +++ b/src/main/resources/db/changelog/changesets/changelog_20251113T131808Z.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index c86fdf9f0..c3ae3006e 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -350,3 +350,6 @@ databaseChangeLog: - include: file: changesets/changelog_20251013T112601Z.xml relativeToChangelogFile: true + - include: + file: changesets/changelog_20251113T131808Z.xml + relativeToChangelogFile: true diff --git a/src/test/java/org/gridsuite/study/server/NadConfigTest.java b/src/test/java/org/gridsuite/study/server/NadConfigTest.java new file mode 100644 index 000000000..923ce10aa --- /dev/null +++ b/src/test/java/org/gridsuite/study/server/NadConfigTest.java @@ -0,0 +1,256 @@ +/** + * Copyright (c) 2025, 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.study.server; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import org.gridsuite.study.server.dto.diagramgridlayout.nad.NadConfigInfos; +import org.gridsuite.study.server.repository.StudyEntity; +import org.gridsuite.study.server.repository.StudyRepository; +import org.gridsuite.study.server.service.NadConfigService; +import org.gridsuite.study.server.service.SingleLineDiagramService; +import org.gridsuite.study.server.utils.elasticsearch.DisableElasticsearch; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +import static org.gridsuite.study.server.StudyConstants.DELIMITER; +import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@DisableElasticsearch +@ContextConfigurationWithTestChannel +class NadConfigTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private StudyRepository studyRepository; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private SingleLineDiagramService singleLineDiagramService; + + @Autowired + private NadConfigService nadConfigService; + + private WireMockServer wireMockServer; + + @BeforeEach + void setup() { + wireMockServer = new WireMockServer(wireMockConfig().dynamicPort()); + wireMockServer.start(); + String baseUrlWireMock = wireMockServer.baseUrl(); + + singleLineDiagramService.setSingleLineDiagramServerBaseUri(baseUrlWireMock); + } + + @AfterEach + void tearDown() { + wireMockServer.stop(); + studyRepository.deleteAll(); + } + + @Test + @Transactional + void testSaveNewNadConfig() throws Exception { + UUID studyUuid = UUID.randomUUID(); + + studyRepository.save(StudyEntity.builder().id(studyUuid).nadConfigsUuids(new ArrayList<>()).build()); + + NadConfigInfos nadConfigInfos = NadConfigInfos.builder() + .id(null) // New config + .build(); + + String payload = objectMapper.writeValueAsString(nadConfigInfos); + + wireMockServer.stubFor(WireMock.post(DELIMITER + "v1/network-area-diagram/configs") + .willReturn(WireMock.ok() + .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + )); + + MvcResult mvcResult = mockMvc.perform(post("/v1/studies/{studyUuid}/network-area-diagrams/configs", studyUuid) + .contentType(MediaType.APPLICATION_JSON) + .content(payload)) + .andExpect(status().isOk()) + .andReturn(); + + UUID nadConfigUuidResult = objectMapper.readValue(mvcResult.getResponse().getContentAsString(), UUID.class); + + assertNotNull(nadConfigUuidResult); + + wireMockServer.verify(1, WireMock.postRequestedFor(WireMock.urlPathEqualTo(DELIMITER + "v1/network-area-diagram/configs"))); + + Optional studyEntity = studyRepository.findById(studyUuid); + assertTrue(studyEntity.isPresent()); + assertTrue(studyEntity.get().getNadConfigsUuids().contains(nadConfigUuidResult)); + } + + @Test + @Transactional + void testUpdateExistingNadConfig() throws Exception { + UUID studyUuid = UUID.randomUUID(); + UUID existingNadConfigUuid = UUID.randomUUID(); + + List nadConfigsList = new ArrayList<>(); + nadConfigsList.add(existingNadConfigUuid); + studyRepository.save(StudyEntity.builder().id(studyUuid).nadConfigsUuids(nadConfigsList).build()); + + NadConfigInfos nadConfigInfos = NadConfigInfos.builder() + .id(existingNadConfigUuid) // Existing config + .build(); + + String payload = objectMapper.writeValueAsString(nadConfigInfos); + + wireMockServer.stubFor(WireMock.put(DELIMITER + "v1/network-area-diagram/config/" + existingNadConfigUuid) + .willReturn(WireMock.ok())); + + MvcResult mvcResult = mockMvc.perform(post("/v1/studies/{studyUuid}/network-area-diagrams/configs", studyUuid) + .contentType(MediaType.APPLICATION_JSON) + .content(payload)) + .andExpect(status().isOk()) + .andReturn(); + + UUID nadConfigUuidResult = objectMapper.readValue(mvcResult.getResponse().getContentAsString(), UUID.class); + + assertEquals(existingNadConfigUuid, nadConfigUuidResult); + + wireMockServer.verify(1, WireMock.putRequestedFor(WireMock.urlPathEqualTo(DELIMITER + "v1/network-area-diagram/config/" + existingNadConfigUuid))); + + Optional studyEntity = studyRepository.findById(studyUuid); + assertTrue(studyEntity.isPresent()); + assertEquals(1, studyEntity.get().getNadConfigsUuids().size()); + assertTrue(studyEntity.get().getNadConfigsUuids().contains(existingNadConfigUuid)); + } + + @Test + @Transactional + void testDeleteNadConfig() throws Exception { + UUID studyUuid = UUID.randomUUID(); + UUID nadConfigUuid = UUID.randomUUID(); + + List nadConfigsList = new ArrayList<>(); + nadConfigsList.add(nadConfigUuid); + studyRepository.save(StudyEntity.builder().id(studyUuid).nadConfigsUuids(nadConfigsList).build()); + + wireMockServer.stubFor(WireMock.delete(DELIMITER + "v1/network-area-diagram/configs") + .willReturn(WireMock.ok())); + + mockMvc.perform(delete("/v1/studies/{studyUuid}/network-area-diagrams/configs/{nadConfigUuid}", studyUuid, nadConfigUuid)) + .andExpect(status().isNoContent()); + + wireMockServer.verify(1, WireMock.deleteRequestedFor(WireMock.urlPathEqualTo(DELIMITER + "v1/network-area-diagram/configs"))); + + Optional studyEntity = studyRepository.findById(studyUuid); + assertTrue(studyEntity.isPresent()); + assertFalse(studyEntity.get().getNadConfigsUuids().contains(nadConfigUuid)); + } + + @Test + void testNadConfigServiceDeleteConfigWithNull() { + nadConfigService.deleteNadConfig(null); + + // Verify no external calls were made + wireMockServer.verify(0, WireMock.deleteRequestedFor(WireMock.urlMatching(".*"))); + } + + @Test + void testNadConfigServiceDeleteMultipleConfigs() { + List nadConfigUuids = List.of(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()); + + wireMockServer.stubFor(WireMock.delete(DELIMITER + "v1/network-area-diagram/configs") + .willReturn(WireMock.ok())); + + nadConfigService.deleteNadConfigs(nadConfigUuids); + + wireMockServer.verify(1, WireMock.deleteRequestedFor(WireMock.urlPathEqualTo(DELIMITER + "v1/network-area-diagram/configs"))); + } + + @Test + void testNadConfigServiceDeleteMultipleConfigsWithNull() { + nadConfigService.deleteNadConfigs(null); + + // Verify no external calls were made + wireMockServer.verify(0, WireMock.deleteRequestedFor(WireMock.urlMatching(".*"))); + } + + @Test + void testNadConfigServiceDeleteMultipleConfigsWithEmptyList() { + nadConfigService.deleteNadConfigs(List.of()); + + // Verify no external calls were made + wireMockServer.verify(0, WireMock.deleteRequestedFor(WireMock.urlMatching(".*"))); + } + + @Test + void testNadConfigServiceCreateWithError() { + NadConfigInfos nadConfigInfos = NadConfigInfos.builder() + .id(null) + .build(); + + wireMockServer.stubFor(WireMock.post(DELIMITER + "v1/network-area-diagram/configs") + .willReturn(WireMock.serverError())); + + StudyException exception = assertThrows(StudyException.class, () -> { + nadConfigService.saveNadConfig(nadConfigInfos); + }); + + assertEquals(StudyException.Type.SAVE_NAD_CONFIG_FAILED, exception.getType()); + } + + @Test + void testNadConfigServiceUpdateWithError() { + UUID existingUuid = UUID.randomUUID(); + NadConfigInfos nadConfigInfos = NadConfigInfos.builder() + .id(existingUuid) + .build(); + + wireMockServer.stubFor(WireMock.put(DELIMITER + "v1/network-area-diagram/config/" + existingUuid) + .willReturn(WireMock.serverError())); + + StudyException exception = assertThrows(StudyException.class, () -> { + nadConfigService.saveNadConfig(nadConfigInfos); + }); + + assertEquals(StudyException.Type.SAVE_NAD_CONFIG_FAILED, exception.getType()); + } + + @Test + void testNadConfigServiceDeleteWithError() { + UUID nadConfigUuid = UUID.randomUUID(); + + wireMockServer.stubFor(WireMock.delete(DELIMITER + "v1/network-area-diagram/configs") + .willReturn(WireMock.serverError())); + + StudyException exception = assertThrows(StudyException.class, () -> { + nadConfigService.deleteNadConfig(nadConfigUuid); + }); + + assertEquals(StudyException.Type.DELETE_NAD_CONFIG_FAILED, exception.getType()); + } +} diff --git a/src/test/java/org/gridsuite/study/server/service/StudyServiceCreateGridLayoutTest.java b/src/test/java/org/gridsuite/study/server/service/StudyServiceCreateGridLayoutTest.java index dacad2021..20ddaad88 100644 --- a/src/test/java/org/gridsuite/study/server/service/StudyServiceCreateGridLayoutTest.java +++ b/src/test/java/org/gridsuite/study/server/service/StudyServiceCreateGridLayoutTest.java @@ -25,7 +25,7 @@ void setUp() { null, null, null, null, null, null, null, null, null, singleLineDiagramService, null, null, null, null, null, null, null, null, null, null, - null, studyConfigService, null, null, null, null, null, + null, studyConfigService, null, null, null, null, null, null, null, null, directoryService); }