diff --git a/openapi/openapi.json b/openapi/openapi.json index 8739dc4..eee2ec7 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -32,8 +32,8 @@ } ], "responses": { - "500": { - "description": "Service unavailable.", + "200": { + "description": "Obtained all enrollments for the creditor institution.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -45,7 +45,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ProblemJson" + "$ref": "#/components/schemas/OrganizationModelResponse" } } } @@ -61,8 +61,8 @@ } } }, - "200": { - "description": "Obtained all enrollments for the creditor institution.", + "404": { + "description": "Not found the creditor institution.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -74,13 +74,13 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OrganizationModelResponse" + "$ref": "#/components/schemas/ProblemJson" } } } }, - "404": { - "description": "Not found the creditor institution.", + "500": { + "description": "Service unavailable.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -135,8 +135,8 @@ "required": true }, "responses": { - "200": { - "description": "Request updated.", + "400": { + "description": "Malformed request.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -148,13 +148,13 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OrganizationModelResponse" + "$ref": "#/components/schemas/ProblemJson" } } } }, - "500": { - "description": "Service unavailable.", + "401": { + "description": "Wrong or missing function key.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -162,17 +162,10 @@ "type": "string" } } - }, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemJson" - } - } } }, - "404": { - "description": "Not found the creditor institution.", + "200": { + "description": "Request updated.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -184,13 +177,13 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ProblemJson" + "$ref": "#/components/schemas/OrganizationModelResponse" } } } }, - "401": { - "description": "Wrong or missing function key.", + "404": { + "description": "Not found the creditor institution.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -198,10 +191,17 @@ "type": "string" } } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemJson" + } + } } }, - "400": { - "description": "Malformed request.", + "500": { + "description": "Service unavailable.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -256,8 +256,8 @@ "required": true }, "responses": { - "500": { - "description": "Service unavailable.", + "409": { + "description": "The organization to create already exists.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -274,8 +274,8 @@ } } }, - "201": { - "description": "Request created.", + "400": { + "description": "Malformed request.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -287,13 +287,13 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OrganizationModelResponse" + "$ref": "#/components/schemas/ProblemJson" } } } }, - "409": { - "description": "The organization to create already exists.", + "401": { + "description": "Wrong or missing function key.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -301,17 +301,10 @@ "type": "string" } } - }, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemJson" - } - } } }, - "401": { - "description": "Wrong or missing function key.", + "500": { + "description": "Service unavailable.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -319,10 +312,17 @@ "type": "string" } } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemJson" + } + } } }, - "400": { - "description": "Malformed request.", + "201": { + "description": "Request created.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -334,7 +334,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ProblemJson" + "$ref": "#/components/schemas/OrganizationModelResponse" } } } @@ -388,8 +388,8 @@ } ], "responses": { - "500": { - "description": "Service unavailable.", + "200": { + "description": "Obtained single enrollment.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -401,13 +401,13 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ProblemJson" + "$ref": "#/components/schemas/EnrollmentModelResponse" } } } }, - "404": { - "description": "Not found the enroll service.", + "401": { + "description": "Wrong or missing function key.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -415,17 +415,10 @@ "type": "string" } } - }, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemJson" - } - } } }, - "200": { - "description": "Obtained single enrollment.", + "500": { + "description": "Service unavailable.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -437,13 +430,13 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EnrollmentModelResponse" + "$ref": "#/components/schemas/ProblemJson" } } } }, - "401": { - "description": "Wrong or missing function key.", + "404": { + "description": "Not found the enroll service.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -451,6 +444,13 @@ "type": "string" } } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemJson" + } + } } } }, @@ -500,8 +500,8 @@ "required": true }, "responses": { - "200": { - "description": "Request updated.", + "404": { + "description": "Not found the creditor institution or the enroll service.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -513,13 +513,13 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OrganizationModelResponse" + "$ref": "#/components/schemas/ProblemJson" } } } }, - "500": { - "description": "Service unavailable.", + "400": { + "description": "Malformed request.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -536,8 +536,8 @@ } } }, - "404": { - "description": "Not found the creditor institution or the enroll service.", + "401": { + "description": "Wrong or missing function key.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -545,17 +545,10 @@ "type": "string" } } - }, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemJson" - } - } } }, - "401": { - "description": "Wrong or missing function key.", + "200": { + "description": "Request updated.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -563,10 +556,17 @@ "type": "string" } } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationModelResponse" + } + } } }, - "400": { - "description": "Malformed request.", + "500": { + "description": "Service unavailable.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -630,8 +630,8 @@ "required": true }, "responses": { - "409": { - "description": "The enrollment to the service already exists.", + "404": { + "description": "Not found the creditor institution or the enroll service.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -648,8 +648,8 @@ } } }, - "500": { - "description": "Service unavailable.", + "400": { + "description": "Malformed request.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -666,8 +666,8 @@ } } }, - "201": { - "description": "Request created.", + "401": { + "description": "Wrong or missing function key.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -675,17 +675,10 @@ "type": "string" } } - }, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OrganizationModelResponse" - } - } } }, - "404": { - "description": "Not found the creditor institution or the enroll service.", + "500": { + "description": "Service unavailable.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -702,8 +695,8 @@ } } }, - "401": { - "description": "Wrong or missing function key.", + "409": { + "description": "The enrollment to the service already exists.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -711,10 +704,17 @@ "type": "string" } } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemJson" + } + } } }, - "400": { - "description": "Malformed request.", + "201": { + "description": "Request created.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -726,7 +726,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ProblemJson" + "$ref": "#/components/schemas/OrganizationModelResponse" } } } @@ -768,8 +768,8 @@ } ], "responses": { - "500": { - "description": "Service unavailable.", + "404": { + "description": "Not found the creditor institution or the enroll service.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -786,6 +786,17 @@ } } }, + "401": { + "description": "Wrong or missing function key.", + "headers": { + "X-Request-Id": { + "description": "This header identifies the call", + "schema": { + "type": "string" + } + } + } + }, "200": { "description": "Request deleted.", "headers": { @@ -804,8 +815,8 @@ } } }, - "404": { - "description": "Not found the creditor institution or the enroll service.", + "500": { + "description": "Service unavailable.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -821,17 +832,6 @@ } } } - }, - "401": { - "description": "Wrong or missing function key.", - "headers": { - "X-Request-Id": { - "description": "This header identifies the call", - "schema": { - "type": "string" - } - } - } } }, "security": [ @@ -901,8 +901,8 @@ } } }, - "500": { - "description": "Service unavailable.", + "400": { + "description": "Malformed request.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -919,8 +919,8 @@ } } }, - "409": { - "description": "Conflict: duplicate debt position found.", + "401": { + "description": "Wrong or missing function key.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -928,17 +928,10 @@ "type": "string" } } - }, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemJson" - } - } } }, - "401": { - "description": "Wrong or missing function key.", + "409": { + "description": "Conflict: duplicate debt position found.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -946,10 +939,17 @@ "type": "string" } } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemJson" + } + } } }, - "400": { - "description": "Malformed request.", + "500": { + "description": "Service unavailable.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -995,8 +995,8 @@ "summary": "Return all services.", "operationId": "getServices", "responses": { - "500": { - "description": "Service unavailable.", + "200": { + "description": "Obtained all enrollments for the creditor institution.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -1008,7 +1008,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ProblemJson" + "$ref": "#/components/schemas/OrganizationModelResponse" } } } @@ -1024,8 +1024,8 @@ } } }, - "200": { - "description": "Obtained all enrollments for the creditor institution.", + "500": { + "description": "Service unavailable.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -1037,7 +1037,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OrganizationModelResponse" + "$ref": "#/components/schemas/ProblemJson" } } } @@ -1082,8 +1082,8 @@ } ], "responses": { - "500": { - "description": "Service unavailable.", + "200": { + "description": "Obtained single service details.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -1095,13 +1095,13 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ProblemJson" + "$ref": "#/components/schemas/ServiceDetailModelResponse" } } } }, - "200": { - "description": "Obtained single service details.", + "404": { + "description": "No service found.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -1113,7 +1113,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ServiceDetailModelResponse" + "$ref": "#/components/schemas/ProblemJson" } } } @@ -1129,8 +1129,8 @@ } } }, - "404": { - "description": "No service found.", + "500": { + "description": "Service unavailable.", "headers": { "X-Request-Id": { "description": "This header identifies the call", @@ -1186,6 +1186,28 @@ } } }, + "ProblemJson": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable" + }, + "status": { + "maximum": 600, + "minimum": 100, + "type": "integer", + "description": "The HTTP status code generated by the origin server for this occurrence of the problem.", + "format": "int32", + "example": 200 + }, + "detail": { + "type": "string", + "description": "A human readable explanation specific to this occurrence of the problem.", + "example": "There was an error processing the request" + } + } + }, "EnrollmentModelResponse": { "required": [ "iban", @@ -1233,28 +1255,6 @@ } } }, - "ProblemJson": { - "type": "object", - "properties": { - "title": { - "type": "string", - "description": "A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable" - }, - "status": { - "maximum": 600, - "minimum": 100, - "type": "integer", - "description": "The HTTP status code generated by the origin server for this occurrence of the problem.", - "format": "int32", - "example": 200 - }, - "detail": { - "type": "string", - "description": "A human readable explanation specific to this occurrence of the problem.", - "example": "There was an error processing the request" - } - } - }, "EnrollmentModel": { "type": "object", "properties": { diff --git a/pom.xml b/pom.xml index 923dc01..8fce206 100644 --- a/pom.xml +++ b/pom.xml @@ -1,112 +1,122 @@ - 4.0.0 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.7.0 - - + + org.springframework.boot + spring-boot-starter-parent + 2.7.0 + + - it.gov.pagopa - spontaneouspayment - 0.0.1 - Gestione Pagamenti Spontanei - Progetto Gestione Pagamenti Spontanei + it.gov.pagopa + spontaneouspayment + 0.0.1 + Gestione Pagamenti Spontanei + Progetto Gestione Pagamenti Spontanei - - 11 - 1.17.2 - 3.0.0 - 1.6.9 - 3.21.0 - 3.1.3 - 3.1.0 - + + 11 + 1.17.2 + 3.0.0 + 1.6.9 + 3.21.0 + 3.1.3 + 3.1.0 + - - - com.azure - azure-spring-data-cosmos - ${cosmos-data-version} - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-validation - - - org.springframework.retry - spring-retry - - - org.hibernate.validator - hibernate-validator - - - org.springdoc - springdoc-openapi-ui - ${springdoc-version} - - - org.springframework.cloud - spring-cloud-starter-openfeign - ${openfeign-version} - - - org.modelmapper - modelmapper - ${modelmapper-version} - - - org.springframework - spring-context - - - org.aspectj - aspectjweaver - compile - - - org.projectlombok - lombok - true - - - org.springframework.boot - spring-boot-starter-test + + + com.azure + azure-spring-data-cosmos + ${cosmos-data-version} + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.retry + spring-retry + + + org.hibernate.validator + hibernate-validator + + + org.springdoc + springdoc-openapi-ui + ${springdoc-version} + + + org.springframework.cloud + spring-cloud-starter-openfeign + ${openfeign-version} + + + org.modelmapper + modelmapper + ${modelmapper-version} + + + org.springframework + spring-context + + + org.aspectj + aspectjweaver + compile + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.testcontainers + azure + test + + + org.testcontainers + junit-jupiter test - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - - - - - - org.testcontainers - testcontainers-bom - ${testcontainers.version} - pom - import - - - + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + + + org.testcontainers + testcontainers-bom + ${testcontainers.version} + pom + import + + + - - - - org.springframework.boot - spring-boot-maven-plugin - - - + + + + org.springframework.boot + spring-boot-maven-plugin + + + diff --git a/src/main/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsService.java b/src/main/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsService.java index 58f2dfb..20ced16 100644 --- a/src/main/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsService.java +++ b/src/main/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsService.java @@ -17,8 +17,12 @@ import it.gov.pagopa.spontaneouspayment.model.OrganizationModel; import it.gov.pagopa.spontaneouspayment.repository.OrganizationRepository; import it.gov.pagopa.spontaneouspayment.repository.ServiceRepository; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; @Service +@AllArgsConstructor +@NoArgsConstructor public class EnrollmentsService { @Autowired diff --git a/src/test/java/it/gov/pagopa/spontaneouspayment/CosmosDBContainerTest.java b/src/test/java/it/gov/pagopa/spontaneouspayment/CosmosDBContainerTest.java new file mode 100644 index 0000000..3de371d --- /dev/null +++ b/src/test/java/it/gov/pagopa/spontaneouspayment/CosmosDBContainerTest.java @@ -0,0 +1,76 @@ +package it.gov.pagopa.spontaneouspayment; + +import static org.junit.Assert.assertTrue; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; + +import org.junit.jupiter.api.Assertions; +import org.junit.Rule; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.rules.TemporaryFolder; +import org.testcontainers.containers.CosmosDBEmulatorContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; + +import com.azure.cosmos.CosmosAsyncClient; +import com.azure.cosmos.CosmosClientBuilder; +import com.azure.cosmos.models.CosmosContainerResponse; +import com.azure.cosmos.models.CosmosDatabaseResponse; + +@Testcontainers +class CosmosDBContainerTest { + + @Rule + public TemporaryFolder tempFolder= new TemporaryFolder(); + + + @Container + private static final CosmosDBEmulatorContainer emulator = new CosmosDBEmulatorContainer( + DockerImageName.parse("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest")); + + + + @BeforeEach + public void setUp() throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException { + tempFolder.create(); + Path keyStoreFile = tempFolder.newFile("azure-cosmos-emulator.keystore").toPath(); + KeyStore keyStore = emulator.buildNewKeyStore(); + keyStore.store(new FileOutputStream(keyStoreFile.toFile()), emulator.getEmulatorKey().toCharArray()); + + System.setProperty("javax.net.ssl.trustStore", keyStoreFile.toString()); + System.setProperty("javax.net.ssl.trustStorePassword", emulator.getEmulatorKey()); + System.setProperty("javax.net.ssl.trustStoreType", "PKCS12"); + } + + @Test + void cosmosDBEmulatorCheck() { + + assertTrue(emulator.isRunning()); + + + + CosmosAsyncClient client = new CosmosClientBuilder() + .gatewayMode() + .endpointDiscoveryEnabled(false) + .endpoint(emulator.getEmulatorEndpoint()) + .key(emulator.getEmulatorKey()) + .buildAsyncClient(); + + CosmosDatabaseResponse databaseResponse = client.createDatabaseIfNotExists("Azure").block(); + + Assertions.assertEquals(201, databaseResponse.getStatusCode()); + CosmosContainerResponse containerResponse = client + .getDatabase("Azure") + .createContainerIfNotExists("ServiceContainer", "/name") + .block(); + Assertions.assertEquals(201, containerResponse.getStatusCode()); + } +} diff --git a/src/test/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsServiceTest.java b/src/test/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsServiceTest.java new file mode 100644 index 0000000..e2d95ac --- /dev/null +++ b/src/test/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsServiceTest.java @@ -0,0 +1,471 @@ +package it.gov.pagopa.spontaneouspayment.service; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.spy; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Rule; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.rules.TemporaryFolder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.testcontainers.containers.CosmosDBEmulatorContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; + +import com.azure.cosmos.CosmosAsyncClient; +import com.azure.cosmos.CosmosClientBuilder; +import com.azure.cosmos.models.CosmosContainerResponse; +import com.azure.cosmos.models.CosmosDatabaseResponse; + +import it.gov.pagopa.spontaneouspayment.entity.Organization; +import it.gov.pagopa.spontaneouspayment.entity.Service; +import it.gov.pagopa.spontaneouspayment.entity.ServiceProperty; +import it.gov.pagopa.spontaneouspayment.entity.ServiceRef; +import it.gov.pagopa.spontaneouspayment.exception.AppException; +import it.gov.pagopa.spontaneouspayment.model.EnrollmentModel; +import it.gov.pagopa.spontaneouspayment.model.OrganizationModel; +import it.gov.pagopa.spontaneouspayment.model.enumeration.Status; +import it.gov.pagopa.spontaneouspayment.repository.OrganizationRepository; +import it.gov.pagopa.spontaneouspayment.repository.ServiceRepository; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@SpringBootTest +@Testcontainers +class EnrollmentsServiceTest { + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + + @Autowired + private OrganizationRepository ciRepository; + + @Autowired + private ServiceRepository serviceRepository; + + @Container + private static final CosmosDBEmulatorContainer emulator = new CosmosDBEmulatorContainer( + DockerImageName.parse("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest")); + + private static EnrollmentsService enrollmentsService; + + @BeforeAll + public void setUp() throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException { + + enrollmentsService = spy(new EnrollmentsService(ciRepository, serviceRepository)); + + tempFolder.create(); + Path keyStoreFile = tempFolder.newFile("azure-cosmos-emulator.keystore").toPath(); + KeyStore keyStore = emulator.buildNewKeyStore(); + keyStore.store(new FileOutputStream(keyStoreFile.toFile()), emulator.getEmulatorKey().toCharArray()); + + System.setProperty("javax.net.ssl.trustStore", keyStoreFile.toString()); + System.setProperty("javax.net.ssl.trustStorePassword", emulator.getEmulatorKey()); + System.setProperty("javax.net.ssl.trustStoreType", "PKCS12"); + + CosmosAsyncClient client = new CosmosClientBuilder().gatewayMode().endpointDiscoveryEnabled(false) + .endpoint(emulator.getEmulatorEndpoint()).key(emulator.getEmulatorKey()).buildAsyncClient(); + + // creation of the database and containers + CosmosDatabaseResponse databaseResponse = client.createDatabaseIfNotExists("db").block(); + + Assertions.assertEquals(201, databaseResponse.getStatusCode()); + CosmosContainerResponse containerResponse = client.getDatabase("db") + .createContainerIfNotExists("creditor_institutions", "/fiscalCode").block(); + Assertions.assertEquals(201, containerResponse.getStatusCode()); + containerResponse = client.getDatabase("db").createContainerIfNotExists("services", "/fiscalCode").block(); + Assertions.assertEquals(201, containerResponse.getStatusCode()); + + // loading the database with test data + Organization ci = new Organization(); + ci.setFiscalCode("organizationTest"); + ci.setCompanyName("Comune di Roma"); + ci.setStatus(Status.ENABLED); + + Service s1 = new Service(); + s1.setId("id-servizio-1"); + s1.setTransferCategory("tassonomia-1"); + s1.setRemittanceInformation("causale-1"); + s1.setBasePath("base-path-1"); + s1.setEndpoint("endpont-1"); + + ServiceProperty sp1 = new ServiceProperty("propName1", "number", true); + List properties1 = new ArrayList<>(); + properties1.add(sp1); + s1.setProperties(properties1); + + Service s2 = new Service(); + s2.setId("id-servizio-2"); + s2.setTransferCategory("tassonomia-2"); + s2.setRemittanceInformation("causale-2"); + s2.setBasePath("base-path-2"); + s2.setEndpoint("endpont-2"); + + ServiceProperty sp2 = new ServiceProperty("propName2", "string", true); + List properties2 = new ArrayList<>(); + properties2.add(sp2); + s2.setProperties(properties2); + + Service s3 = new Service(); + s3.setId("id-servizio-3"); + s3.setTransferCategory("tassonomia-3"); + s3.setRemittanceInformation("causale-3"); + s3.setBasePath("base-path-3"); + s3.setEndpoint("endpont-3"); + + ServiceProperty sp3 = new ServiceProperty("propName3", "url", true); + List properties3 = new ArrayList<>(); + properties3.add(sp3); + s3.setProperties(properties3); + + Service s4 = new Service(); + s4.setId("id-servizio-4"); + s4.setTransferCategory("tassonomia-4"); + s4.setRemittanceInformation("causale-4"); + s4.setBasePath("base-path-4"); + s4.setEndpoint("endpont-4"); + + ServiceProperty sp4 = new ServiceProperty("propName4", "rule", true); + List properties4 = new ArrayList<>(); + properties4.add(sp4); + s4.setProperties(properties4); + + ServiceRef ref1 = new ServiceRef(); + ref1.setServiceId("id-servizio-1"); + ref1.setIban("iban-1"); + ServiceRef ref2 = new ServiceRef(); + ref2.setServiceId("id-servizio-2"); + ref2.setIban("iban-2"); + List servicesRef = new ArrayList<>(); + servicesRef.add(ref1); + servicesRef.add(ref2); + + ci.setEnrollments(servicesRef); + + ciRepository.deleteAll(); + ciRepository.save(ci); + serviceRepository.deleteAll(); + serviceRepository.save(s1); + serviceRepository.save(s2); + serviceRepository.save(s3); + serviceRepository.save(s4); + } + + @AfterAll + void teardown() { + CosmosAsyncClient client = new CosmosClientBuilder().gatewayMode().endpointDiscoveryEnabled(false) + .endpoint(emulator.getEmulatorEndpoint()).key(emulator.getEmulatorKey()).buildAsyncClient(); + client.getDatabase("db").delete(); + emulator.stop(); + } + + + @Test + void getECEnrollments() { + assertTrue(emulator.isRunning()); + Organization org = enrollmentsService.getECEnrollments("organizationTest"); + assertEquals("organizationTest", org.getFiscalCode()); + assertEquals("Comune di Roma", org.getCompanyName()); + } + + @Test + void getECEnrollments_404() { + assertTrue(emulator.isRunning()); + try { + // get a non-existent organization -> must raise a 404 exception + enrollmentsService.getECEnrollments("organizationFake"); + fail(); + } catch (AppException e) { + assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus()); + } catch (Exception e) { + fail(); + } + } + + @Test + void getSingleEnrollment() { + assertTrue(emulator.isRunning()); + ServiceRef enrollment = enrollmentsService.getSingleEnrollment("organizationTest", "id-servizio-1"); + assertEquals("id-servizio-1", enrollment.getServiceId()); + assertEquals(null, enrollment.getOfficeName()); + assertEquals("iban-1", enrollment.getIban()); + } + + @Test + void getSingleEnrollment_404() { + assertTrue(emulator.isRunning()); + try { + // get a non-existent organization -> must raise a 404 exception + enrollmentsService.getSingleEnrollment("organizationFake", "id-servizio-1"); + fail(); + } catch (AppException e) { + assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus()); + } catch (Exception e) { + fail(); + } + + try { + // get a non-existent enrollment -> must raise a 404 exception + enrollmentsService.getSingleEnrollment("organizationTest", "id-servizio-fake"); + fail(); + } catch (AppException e) { + assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus()); + } catch (Exception e) { + fail(); + } + } + + @Test + void createEC() { + assertTrue(emulator.isRunning()); + Organization ci = new Organization(); + ci.setFiscalCode("organizationNew"); + ci.setCompanyName("Comune di Milano"); + ci.setStatus(Status.ENABLED); + ServiceRef ref1 = new ServiceRef(); + ref1.setServiceId("id-servizio-1"); + ref1.setIban("iban-1"); + List servicesRef = new ArrayList<>(); + servicesRef.add(ref1); + ci.setEnrollments(servicesRef); + Organization orgCreated = enrollmentsService.createEC(ci); + assertEquals("organizationNew", orgCreated.getFiscalCode()); + assertEquals("Comune di Milano", orgCreated.getCompanyName()); + assertEquals(1, orgCreated.getEnrollments().size()); + } + + @Test + void createEC_404() { + assertTrue(emulator.isRunning()); + // creation of an organization with enroll to a service that does not exist + Organization ci = new Organization(); + ci.setFiscalCode("organizationNoService"); + ci.setCompanyName("Comune di Milano"); + ci.setStatus(Status.ENABLED); + ServiceRef ref1 = new ServiceRef(); + ref1.setServiceId("id-servizio-fake"); + ref1.setIban("iban-1"); + List servicesRef = new ArrayList<>(); + servicesRef.add(ref1); + ci.setEnrollments(servicesRef); + + try { + // must raise a 404 exception + enrollmentsService.createEC(ci); + fail(); + } catch (AppException e) { + assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus()); + } catch (Exception e) { + fail(); + } + } + + @Test + void createEC_409() { + assertTrue(emulator.isRunning()); + // creation of an organization already present in the system + Organization ci = new Organization(); + ci.setFiscalCode("organizationTest"); + ci.setCompanyName("Comune di Milano"); + ci.setStatus(Status.ENABLED); + ServiceRef ref1 = new ServiceRef(); + ref1.setServiceId("id-servizio-1"); + ref1.setIban("iban-1"); + List servicesRef = new ArrayList<>(); + servicesRef.add(ref1); + ci.setEnrollments(servicesRef); + try { + // must raise a 409 exception + enrollmentsService.createEC(ci); + fail(); + } catch (AppException e) { + assertEquals(HttpStatus.CONFLICT, e.getHttpStatus()); + } catch (Exception e) { + fail(); + } + } + + @Test + void createECEnrollment() { + assertTrue(emulator.isRunning()); + EnrollmentModel enrollment = + EnrollmentModel.builder().iban("iban-3").officeName("Ufficio Tributario").build(); + Organization org = enrollmentsService.createECEnrollment("organizationTest", "id-servizio-3", enrollment); + assertEquals("organizationTest", org.getFiscalCode()); + assertEquals("Comune di Roma", org.getCompanyName()); + // added an enrollment -> the size became 3 + assertEquals(3, org.getEnrollments().size()); + } + + @Test + void createECEnrollment_404() { + assertTrue(emulator.isRunning()); + EnrollmentModel enrollment = + EnrollmentModel.builder().iban("iban-3").officeName("Ufficio Tributario").build(); + + try { + // non-existent organization -> must raise a 404 exception + enrollmentsService.createECEnrollment("organizationFake", "id-servizio-1", enrollment); + fail(); + } catch (AppException e) { + assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus()); + } catch (Exception e) { + fail(); + } + + try { + // non-existent service -> must raise a 404 exception + enrollmentsService.createECEnrollment("organizationTest", "id-servizio-fake", enrollment); + fail(); + } catch (AppException e) { + assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus()); + } catch (Exception e) { + fail(); + } + } + + @Test + void createECEnrollment_409() { + assertTrue(emulator.isRunning()); + EnrollmentModel enrollment = + EnrollmentModel.builder().iban("iban-3").officeName("Ufficio Tributario").build(); + + try { + // enrollment to service already exist -> must raise a 409 exception + enrollmentsService.createECEnrollment("organizationTest", "id-servizio-1", enrollment); + fail(); + } catch (AppException e) { + assertEquals(HttpStatus.CONFLICT, e.getHttpStatus()); + } catch (Exception e) { + fail(); + } + + + } + + @Test + void updateECEnrollment() { + assertTrue(emulator.isRunning()); + EnrollmentModel enrollment = + EnrollmentModel.builder().iban("iban-updated-2").officeName("Ufficio Tributario Updated").build(); + Organization org = enrollmentsService.updateECEnrollment("organizationTest", "id-servizio-2", enrollment); + assertEquals("organizationTest", org.getFiscalCode()); + assertEquals("Comune di Roma", org.getCompanyName()); + ServiceRef updatedEnrollment = org.getEnrollments().stream().filter(s -> s.getServiceId().equals("id-servizio-2")).findFirst().get(); + assertEquals("iban-updated-2", updatedEnrollment.getIban()); + assertEquals("Ufficio Tributario Updated", updatedEnrollment.getOfficeName()); + } + + @Test + void updateECEnrollment_404() { + assertTrue(emulator.isRunning()); + EnrollmentModel enrollment = + EnrollmentModel.builder().iban("iban-updated-2").officeName("Ufficio Tributario Updated").build(); + try { + // non-existent organization -> must raise a 404 exception + enrollmentsService.updateECEnrollment("organizationFake", "id-servizio-2", enrollment); + fail(); + } catch (AppException e) { + assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus()); + } catch (Exception e) { + fail(); + } + + try { + // non-existent service -> must raise a 404 exception + enrollmentsService.updateECEnrollment("organizationTest", "id-servizio-fake", enrollment); + fail(); + } catch (AppException e) { + assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus()); + } catch (Exception e) { + fail(); + } + } + + @Test + void updateEC() { + assertTrue(emulator.isRunning()); + OrganizationModel orgModel = OrganizationModel.builder().companyName("Comune di Roma").status(Status.DISABLED).build(); + Organization org = enrollmentsService.updateEC("organizationTest", orgModel); + assertEquals("organizationTest", org.getFiscalCode()); + assertEquals("Comune di Roma", org.getCompanyName()); + assertEquals(Status.DISABLED, org.getStatus()); + } + + @Test + void updateEC_404() { + assertTrue(emulator.isRunning()); + OrganizationModel orgModel = OrganizationModel.builder().companyName("Comune di Roma").status(Status.DISABLED).build(); + try { + // non-existent organization -> must raise a 404 exception + enrollmentsService.updateEC("organizationFake", orgModel); + fail(); + } catch (AppException e) { + assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus()); + } catch (Exception e) { + fail(); + } + } + + @Test + void deleteECEnrollment() { + assertTrue(emulator.isRunning()); + // Add a dummy enrollment + EnrollmentModel enrollment = + EnrollmentModel.builder().iban("iban-4").officeName("Ufficio Tributario 4").build(); + Organization org = enrollmentsService.createECEnrollment("organizationTest", "id-servizio-4", enrollment); + assertEquals("organizationTest", org.getFiscalCode()); + assertEquals("Comune di Roma", org.getCompanyName()); + ServiceRef addedEnrollment = org.getEnrollments().stream().filter(s -> s.getServiceId().equals("id-servizio-4")).findFirst().get(); + assertEquals("iban-4", addedEnrollment.getIban()); + assertEquals("Ufficio Tributario 4", addedEnrollment.getOfficeName()); + + // Remove the dummy enrollment + enrollmentsService.deleteECEnrollment("organizationTest", "id-servizio-4"); + // This line means the call was successful + assertTrue(true); + } + + @Test + void deleteECEnrollment_404() { + assertTrue(emulator.isRunning()); + try { + // non-existent organization -> must raise a 404 exception + enrollmentsService.deleteECEnrollment("organizationFake", "id-servizio-4"); + fail(); + } catch (AppException e) { + assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus()); + } catch (Exception e) { + fail(); + } + + try { + // non-existent enrollment -> must raise a 404 exception + enrollmentsService.deleteECEnrollment("organizationTest", "id-servizio-fake"); + fail(); + } catch (AppException e) { + assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus()); + } catch (Exception e) { + fail(); + } + + } + +}