diff --git a/.github/workflows/sampledata-ci.yaml b/.github/workflows/sampledata-ci.yaml index b3c7db5ed4..84df35e065 100644 --- a/.github/workflows/sampledata-ci.yaml +++ b/.github/workflows/sampledata-ci.yaml @@ -2,23 +2,23 @@ name: sampledata service ci on: push: - branches: ["main"] + branches: ['main'] paths: - - "sampledata/**" - - ".github/workflows/actions/action.yaml" - - ".github/workflows/sampledata-ci.yaml" - - "pom.xml" + - 'sampledata/**' + - '.github/workflows/actions/action.yaml' + - '.github/workflows/sampledata-ci.yaml' + - 'pom.xml' pull_request: - branches: ["main"] + branches: ['main'] paths: - - "sampledata/**" - - ".github/workflows/actions/action.yaml" - - ".github/workflows/sampledata-ci.yaml" - - "pom.xml" + - 'sampledata/**' + - '.github/workflows/actions/action.yaml' + - '.github/workflows/sampledata-ci.yaml' + - 'pom.xml' workflow_dispatch: jobs: - Build: + Test: runs-on: ubuntu-latest env: FROM_ORIGINAL_REPOSITORY: ${{ github.event.pull_request.head.repo.full_name == github.repository || github.ref == 'refs/heads/main' }} @@ -26,48 +26,52 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - uses: ./.github/workflows/actions - - name: Run Maven Build Command + + - name: Run tests and generate coverage report run: mvn clean install -pl sampledata -am + - name: Run Maven Checkstyle if: ${{ env.FROM_ORIGINAL_REPOSITORY == 'true' }} run: mvn checkstyle:checkstyle -pl sampledata -am -Dcheckstyle.output.file=sampledata-checkstyle-result.xml + - name: Upload Checkstyle Result if: ${{ env.FROM_ORIGINAL_REPOSITORY == 'true' }} uses: jwgmeligmeyling/checkstyle-github-action@master with: path: '**/sampledata-checkstyle-result.xml' + + - name: Upload test results + uses: dorny/test-reporter@v1 + if: ${{ env.FROM_ORIGINAL_REPOSITORY == 'true' && (success() || failure()) }} + with: + name: Sampledata-Service-Unit-Test-Results + path: 'sampledata/**/*-reports/TEST*.xml' + reporter: java-junit + + - name: Add coverage report to PR + uses: madrapps/jacoco-report@v1.6.1 + if: ${{ env.FROM_ORIGINAL_REPOSITORY == 'true' }} + with: + paths: ${{github.workspace}}/sampledata/target/site/jacoco/jacoco.xml + token: ${{secrets.GITHUB_TOKEN}} + min-coverage-overall: 70 + min-coverage-changed-files: 70 + title: 'Sampledata Coverage Report' + update-comment: true + - name: Analyze with sonar cloud if: ${{ env.FROM_ORIGINAL_REPOSITORY == 'true' }} env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} run: mvn org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -f sampledata - - name: OWASP Dependency Check - if: ${{ env.FROM_ORIGINAL_REPOSITORY == 'true' }} - uses: dependency-check/Dependency-Check_Action@main - env: - JAVA_HOME: /opt/jdk - with: - project: 'yas' - path: '.' - format: 'HTML' - - name: Upload OWASP Dependency Check results - if: ${{ env.FROM_ORIGINAL_REPOSITORY == 'true' }} - uses: actions/upload-artifact@master - with: - name: OWASP Dependency Check Report - path: ${{github.workspace}}/reports - - name: Log in to the Container registry - if: ${{ github.ref == 'refs/heads/main' }} - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and push Docker images - if: ${{ github.ref == 'refs/heads/main' }} - uses: docker/build-push-action@v6 - with: - context: ./sampledata - push: true - tags: ghcr.io/nashtech-garage/yas-sampledata:latest \ No newline at end of file + + Build: + runs-on: ubuntu-latest + needs: Test + steps: + - uses: actions/checkout@v4 + - uses: ./.github/workflows/actions + - name: Build artifact + run: mvn clean install -pl sampledata -am -DskipTests \ No newline at end of file diff --git a/sampledata/pom.xml b/sampledata/pom.xml index d31d5535ca..2530210f60 100644 --- a/sampledata/pom.xml +++ b/sampledata/pom.xml @@ -14,9 +14,9 @@ YAS sampledata service - nashtech-garage + longtoz https://sonarcloud.io - nashtech-garage_yas-sampledata + longtoz_yas-sampledata diff --git a/sampledata/src/test/java/com/yas/sampledata/SampledataJacocoSmokeTest.java b/sampledata/src/test/java/com/yas/sampledata/SampledataJacocoSmokeTest.java new file mode 100644 index 0000000000..480efe63c6 --- /dev/null +++ b/sampledata/src/test/java/com/yas/sampledata/SampledataJacocoSmokeTest.java @@ -0,0 +1,13 @@ +package com.yas.sampledata; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +class SampledataJacocoSmokeTest { + + @Test + void jacocoSmokeTest() { + assertTrue(true); + } +} diff --git a/sampledata/src/test/java/com/yas/sampledata/config/DataSourceConfigTest.java b/sampledata/src/test/java/com/yas/sampledata/config/DataSourceConfigTest.java new file mode 100644 index 0000000000..84a64cdfe2 --- /dev/null +++ b/sampledata/src/test/java/com/yas/sampledata/config/DataSourceConfigTest.java @@ -0,0 +1,31 @@ +package com.yas.sampledata.config; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import javax.sql.DataSource; +import org.junit.jupiter.api.Test; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.util.ReflectionTestUtils; + +class DataSourceConfigTest { + + @Test + void dataSources_andJdbcTemplates_areCreated() { + DataSourceConfig config = new DataSourceConfig(); + ReflectionTestUtils.setField(config, "driverClassName", "org.h2.Driver"); + ReflectionTestUtils.setField(config, "username", "sa"); + ReflectionTestUtils.setField(config, "password", ""); + ReflectionTestUtils.setField(config, "productUrl", "jdbc:h2:mem:sampledata_product;DB_CLOSE_DELAY=-1"); + ReflectionTestUtils.setField(config, "mediaUrl", "jdbc:h2:mem:sampledata_media;DB_CLOSE_DELAY=-1"); + + DataSource product = config.productDataSource(); + DataSource media = config.mediaDataSource(); + JdbcTemplate productJdbc = config.jdbcProduct(product); + JdbcTemplate mediaJdbc = config.jdbcMedia(media); + + assertNotNull(product); + assertNotNull(media); + assertNotNull(productJdbc); + assertNotNull(mediaJdbc); + } +} diff --git a/sampledata/src/test/java/com/yas/sampledata/config/RestClientConfigTest.java b/sampledata/src/test/java/com/yas/sampledata/config/RestClientConfigTest.java new file mode 100644 index 0000000000..faca61ef01 --- /dev/null +++ b/sampledata/src/test/java/com/yas/sampledata/config/RestClientConfigTest.java @@ -0,0 +1,15 @@ +package com.yas.sampledata.config; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.Test; + +class RestClientConfigTest { + + @Test + void restClient_isCreated() { + RestClientConfig config = new RestClientConfig(); + + assertNotNull(config.restClient()); + } +} diff --git a/sampledata/src/test/java/com/yas/sampledata/config/SecurityConfigTest.java b/sampledata/src/test/java/com/yas/sampledata/config/SecurityConfigTest.java new file mode 100644 index 0000000000..0a6a052481 --- /dev/null +++ b/sampledata/src/test/java/com/yas/sampledata/config/SecurityConfigTest.java @@ -0,0 +1,31 @@ +package com.yas.sampledata.config; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; + +class SecurityConfigTest { + + @Test + void jwtAuthenticationConverterForKeycloak_mapsRolesToAuthorities() { + SecurityConfig config = new SecurityConfig(); + var converter = config.jwtAuthenticationConverterForKeycloak(); + + Jwt jwt = Jwt.withTokenValue("token") + .header("alg", "none") + .claim("realm_access", Map.of("roles", List.of("ADMIN", "USER"))) + .subject("user-1") + .build(); + + JwtAuthenticationToken auth = (JwtAuthenticationToken) converter.convert(jwt); + + assertEquals("user-1", auth.getName()); + assertTrue(auth.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))); + assertTrue(auth.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_USER"))); + } +} diff --git a/sampledata/src/test/java/com/yas/sampledata/config/SwaggerConfigTest.java b/sampledata/src/test/java/com/yas/sampledata/config/SwaggerConfigTest.java new file mode 100644 index 0000000000..70978fde1a --- /dev/null +++ b/sampledata/src/test/java/com/yas/sampledata/config/SwaggerConfigTest.java @@ -0,0 +1,19 @@ +package com.yas.sampledata.config; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import org.junit.jupiter.api.Test; + +class SwaggerConfigTest { + + @Test + void annotations_arePresent() { + OpenAPIDefinition openApi = SwaggerConfig.class.getAnnotation(OpenAPIDefinition.class); + SecurityScheme securityScheme = SwaggerConfig.class.getAnnotation(SecurityScheme.class); + + assertNotNull(openApi); + assertNotNull(securityScheme); + } +} diff --git a/sampledata/src/test/java/com/yas/sampledata/controller/SampleDataControllerTest.java b/sampledata/src/test/java/com/yas/sampledata/controller/SampleDataControllerTest.java new file mode 100644 index 0000000000..5df48dc5cc --- /dev/null +++ b/sampledata/src/test/java/com/yas/sampledata/controller/SampleDataControllerTest.java @@ -0,0 +1,26 @@ +package com.yas.sampledata.controller; + +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.yas.sampledata.service.SampleDataService; +import com.yas.sampledata.viewmodel.SampleDataVm; +import org.junit.jupiter.api.Test; + +class SampleDataControllerTest { + + @Test + void createSampleData_delegatesToService() { + SampleDataService service = mock(SampleDataService.class); + SampleDataVm expected = new SampleDataVm("ok"); + when(service.createSampleData()).thenReturn(expected); + SampleDataController controller = new SampleDataController(service); + + SampleDataVm result = controller.createSampleData(new SampleDataVm("ignored")); + + assertSame(expected, result); + verify(service).createSampleData(); + } +} diff --git a/sampledata/src/test/java/com/yas/sampledata/service/SampleDataServiceTest.java b/sampledata/src/test/java/com/yas/sampledata/service/SampleDataServiceTest.java new file mode 100644 index 0000000000..eb467f944b --- /dev/null +++ b/sampledata/src/test/java/com/yas/sampledata/service/SampleDataServiceTest.java @@ -0,0 +1,29 @@ +package com.yas.sampledata.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.yas.sampledata.viewmodel.SampleDataVm; +import javax.sql.DataSource; +import org.h2.jdbcx.JdbcDataSource; +import org.junit.jupiter.api.Test; + +class SampleDataServiceTest { + + @Test + void createSampleData_returnsSuccessMessage() { + DataSource dataSource = createDataSource("jdbc:h2:mem:sampledata_service;DB_CLOSE_DELAY=-1"); + SampleDataService service = new SampleDataService(dataSource, dataSource); + + SampleDataVm result = service.createSampleData(); + + assertEquals("Insert Sample Data successfully!", result.message()); + } + + private DataSource createDataSource(String url) { + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setURL(url); + dataSource.setUser("sa"); + dataSource.setPassword(""); + return dataSource; + } +} diff --git a/sampledata/src/test/java/com/yas/sampledata/utils/MessagesUtilsTest.java b/sampledata/src/test/java/com/yas/sampledata/utils/MessagesUtilsTest.java new file mode 100644 index 0000000000..ba65b0e614 --- /dev/null +++ b/sampledata/src/test/java/com/yas/sampledata/utils/MessagesUtilsTest.java @@ -0,0 +1,15 @@ +package com.yas.sampledata.utils; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +class MessagesUtilsTest { + + @Test + void getMessage_returnsKeyWhenMissing() { + String message = MessagesUtils.getMessage("UNKNOWN_CODE"); + + assertEquals("UNKNOWN_CODE", message); + } +} diff --git a/sampledata/src/test/java/com/yas/sampledata/utils/SqlScriptExecutorTest.java b/sampledata/src/test/java/com/yas/sampledata/utils/SqlScriptExecutorTest.java new file mode 100644 index 0000000000..26ba03de94 --- /dev/null +++ b/sampledata/src/test/java/com/yas/sampledata/utils/SqlScriptExecutorTest.java @@ -0,0 +1,37 @@ +package com.yas.sampledata.utils; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.sql.Connection; +import java.sql.ResultSet; +import javax.sql.DataSource; +import org.h2.jdbcx.JdbcDataSource; +import org.junit.jupiter.api.Test; + +class SqlScriptExecutorTest { + + @Test + void executeScriptsForSchema_runsSqlScripts() throws Exception { + DataSource dataSource = createDataSource("jdbc:h2:mem:sampledata_utils;DB_CLOSE_DELAY=-1"); + SqlScriptExecutor executor = new SqlScriptExecutor(); + + executor.executeScriptsForSchema(dataSource, "PUBLIC", "classpath*:db/product/*.sql"); + + assertTrue(tableExists(dataSource, "SAMPLE_PRODUCT")); + } + + private DataSource createDataSource(String url) { + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setURL(url); + dataSource.setUser("sa"); + dataSource.setPassword(""); + return dataSource; + } + + private boolean tableExists(DataSource dataSource, String tableName) throws Exception { + try (Connection connection = dataSource.getConnection()) { + ResultSet tables = connection.getMetaData().getTables(null, "PUBLIC", tableName, null); + return tables.next(); + } + } +} diff --git a/sampledata/src/test/java/com/yas/sampledata/viewmodel/ErrorVmTest.java b/sampledata/src/test/java/com/yas/sampledata/viewmodel/ErrorVmTest.java new file mode 100644 index 0000000000..1e56bf08b2 --- /dev/null +++ b/sampledata/src/test/java/com/yas/sampledata/viewmodel/ErrorVmTest.java @@ -0,0 +1,17 @@ +package com.yas.sampledata.viewmodel; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +class ErrorVmTest { + + @Test + void constructor_defaultsFieldErrors() { + ErrorVm vm = new ErrorVm("400", "Bad", "detail"); + + assertNotNull(vm.fieldErrors()); + assertTrue(vm.fieldErrors().isEmpty()); + } +} diff --git a/sampledata/src/test/java/com/yas/sampledata/viewmodel/SampleDataVmTest.java b/sampledata/src/test/java/com/yas/sampledata/viewmodel/SampleDataVmTest.java new file mode 100644 index 0000000000..5b79c70d86 --- /dev/null +++ b/sampledata/src/test/java/com/yas/sampledata/viewmodel/SampleDataVmTest.java @@ -0,0 +1,15 @@ +package com.yas.sampledata.viewmodel; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +class SampleDataVmTest { + + @Test + void recordStoresMessage() { + SampleDataVm vm = new SampleDataVm("message"); + + assertEquals("message", vm.message()); + } +} diff --git a/sampledata/src/test/resources/db/media/sampledata_test.sql b/sampledata/src/test/resources/db/media/sampledata_test.sql new file mode 100644 index 0000000000..d96da9454b --- /dev/null +++ b/sampledata/src/test/resources/db/media/sampledata_test.sql @@ -0,0 +1 @@ +CREATE TABLE IF NOT EXISTS sample_media (id INT PRIMARY KEY); diff --git a/sampledata/src/test/resources/db/product/sampledata_test.sql b/sampledata/src/test/resources/db/product/sampledata_test.sql new file mode 100644 index 0000000000..979ff3b958 --- /dev/null +++ b/sampledata/src/test/resources/db/product/sampledata_test.sql @@ -0,0 +1 @@ +CREATE TABLE IF NOT EXISTS sample_product (id INT PRIMARY KEY);