diff --git a/.github/workflows/Android_test.yml b/.github/workflows/Android_test.yml index e68ffa8..9973f73 100644 --- a/.github/workflows/Android_test.yml +++ b/.github/workflows/Android_test.yml @@ -138,24 +138,28 @@ jobs: -d "{ \"notes\": \"Test plan for App Startup Time metric\", \"testName\": \"Startup Time Plan\", - \"metricMetricId\": 1, + \"metricName\": \"App Startup Time\", \"deviceName\": \"Medium_Phone_API_35\", \"appName\": \"Alfie.apk\", \"appVersion\": \"0.8.0\", \"appPackage\": \"au.com.alfie.ecomm.debug\", \"mainActivity\": \"au.com.alfie.ecomm.MainActivity\", - \"executionTypeExecutionTypeId\": 1, + \"executionType\": \"Cold Start\", \"thresholds\": [ { \"targetValue\": 20000, - \"thresholdTypeThresholdTypeId\": 2, + \"thresholdType\": \"Max\", \"metricOutputMetricOutputId\": 1 } ], \"metricParameters\": [ { \"parameterValue\": \"home-tab\", - \"metricParameterMetricParameterId\": 1 + \"metricParameter\": \"elementToWaitFor\" + }, + { + \"parameterValue\": \"200000\", + \"metricParameter\": \"timeout\" } ], \"executionTypeParameters\": [], @@ -397,4 +401,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: android-backend-log - path: backend.log \ No newline at end of file + path: backend.log diff --git a/.github/workflows/iOS_tests.yml b/.github/workflows/iOS_tests.yml index d7cd1e0..ce02d45 100644 --- a/.github/workflows/iOS_tests.yml +++ b/.github/workflows/iOS_tests.yml @@ -93,27 +93,27 @@ jobs: -d "{ \"notes\": \"Test plan for App Startup Time metric\", \"testName\": \"Startup Time Plan\", - \"metricMetricId\": 1, + \"metricName\": \"App Startup Time\", \"deviceName\": \"iPhone 16 Pro\", \"appName\": \"Alfie.app\", \"appVersion\": \"0.8.1\", \"appPackage\": \"com.mindera.alfie.debug\", - \"executionTypeExecutionTypeId\": 1, + \"executionType\": \"Cold Start\", \"thresholds\": [ { \"targetValue\": 5000, - \"thresholdTypeThresholdTypeId\": 2, + \"thresholdType\": \"Max\", \"metricOutputMetricOutputId\": 1 } ], \"metricParameters\": [ { \"parameterValue\": \"account-btn\", - \"metricParameterMetricParameterId\": 1 + \"metricParameter\": \"elementToWaitFor\" }, { \"parameterValue\": \"200000\", - \"metricParameterMetricParameterId\": 2 + \"metricParameter\": \"timeout\" } ], \"executionTypeParameters\": [], diff --git a/Melmac/src/main/kotlin/controllers/TestExecutionController.kt b/Melmac/src/main/kotlin/controllers/TestExecutionController.kt index 97dbf55..64988ce 100644 --- a/Melmac/src/main/kotlin/controllers/TestExecutionController.kt +++ b/Melmac/src/main/kotlin/controllers/TestExecutionController.kt @@ -2,7 +2,6 @@ package controllers import controllers.IControllers.ITestExecutionController import dtos.TestExecutionResponseDTO -import dtos.TestExecutionRequestDTO import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.response.* diff --git a/Melmac/src/main/kotlin/core/DependencyModule.kt b/Melmac/src/main/kotlin/core/DependencyModule.kt index c2f5bfa..afa1774 100644 --- a/Melmac/src/main/kotlin/core/DependencyModule.kt +++ b/Melmac/src/main/kotlin/core/DependencyModule.kt @@ -52,6 +52,9 @@ val appModule = module { // --- Repositories --- + // Bootstrap Update + single { BootstrapUpdateRepository(get()) } + // Metrics single { MetricRepository(get()) } single { MetricOutputRepository(get()) } @@ -106,6 +109,7 @@ val appModule = module { get(), get(), get(), + get(), get(named("metricsConfigPath")) ) } @@ -132,7 +136,7 @@ val appModule = module { get() ) } - single { ThresholdService(get()) } + single { ThresholdService(get(), get()) } single { ThresholdTypeService(get()) } single { TestPlanService( @@ -149,6 +153,11 @@ val appModule = module { get(), get(), get(), + get(), + get(), + get(), + get(), + get(), get() ) } diff --git a/Melmac/src/main/kotlin/domain/dtos/ConfigDataDTO.kt b/Melmac/src/main/kotlin/domain/dtos/ConfigDataDTO.kt index 41482f7..dc0ddad 100644 --- a/Melmac/src/main/kotlin/domain/dtos/ConfigDataDTO.kt +++ b/Melmac/src/main/kotlin/domain/dtos/ConfigDataDTO.kt @@ -1,6 +1,7 @@ package dtos data class DataConfig( + val lastUpdated: String, val metrics: List, val thresholdTypes: List ) diff --git a/Melmac/src/main/kotlin/domain/dtos/ExecutionTypeMetricRequestDTO.kt b/Melmac/src/main/kotlin/domain/dtos/ExecutionTypeMetricRequestDTO.kt deleted file mode 100644 index 650ae17..0000000 --- a/Melmac/src/main/kotlin/domain/dtos/ExecutionTypeMetricRequestDTO.kt +++ /dev/null @@ -1,6 +0,0 @@ -package dtos - -data class ExecutionTypeMetricRequestDTO( - val executionTypeExecutionTypeId: Int, - val metricMetricId: Int -) diff --git a/Melmac/src/main/kotlin/domain/dtos/SuiteExecutionRequestDTO.kt b/Melmac/src/main/kotlin/domain/dtos/SuiteExecutionRequestDTO.kt deleted file mode 100644 index 17bc7b3..0000000 --- a/Melmac/src/main/kotlin/domain/dtos/SuiteExecutionRequestDTO.kt +++ /dev/null @@ -1,5 +0,0 @@ -package dtos - -data class SuiteExecutionRequestDTO( - val testSuiteVersionTestSuiteVersionId: Int -) diff --git a/Melmac/src/main/kotlin/domain/dtos/TestExecutionRequestDTO.kt b/Melmac/src/main/kotlin/domain/dtos/TestExecutionRequestDTO.kt deleted file mode 100644 index 24adfc6..0000000 --- a/Melmac/src/main/kotlin/domain/dtos/TestExecutionRequestDTO.kt +++ /dev/null @@ -1,5 +0,0 @@ -package dtos - -data class TestExecutionRequestDTO( - val testPlanVersionTestPlanVersionId: Int -) diff --git a/Melmac/src/main/kotlin/domain/dtos/TestExecutionTypeParameterRequestDTO.kt b/Melmac/src/main/kotlin/domain/dtos/TestExecutionTypeParameterRequestDTO.kt index 9220aca..d01ea36 100644 --- a/Melmac/src/main/kotlin/domain/dtos/TestExecutionTypeParameterRequestDTO.kt +++ b/Melmac/src/main/kotlin/domain/dtos/TestExecutionTypeParameterRequestDTO.kt @@ -2,6 +2,6 @@ package dtos data class TestExecutionTypeParameterRequestDTO( val parameterValue: String, - val executionTypeParameterExecutionTypeParameterId: Int, + val executionTypeParameter: String, val testPlanVersionTestPlanVersionId: Int ) diff --git a/Melmac/src/main/kotlin/domain/dtos/TestMetricParameterRequestDTO.kt b/Melmac/src/main/kotlin/domain/dtos/TestMetricParameterRequestDTO.kt index 56d55eb..9c6dd58 100644 --- a/Melmac/src/main/kotlin/domain/dtos/TestMetricParameterRequestDTO.kt +++ b/Melmac/src/main/kotlin/domain/dtos/TestMetricParameterRequestDTO.kt @@ -2,6 +2,6 @@ package dtos data class TestMetricParameterRequestDTO( val parameterValue: String, - val metricParameterMetricParameterId: Int, + val metricParameter: String, val testPlanVersionTestPlanVersionId: Int ) diff --git a/Melmac/src/main/kotlin/domain/dtos/TestPlanRequestDTO.kt b/Melmac/src/main/kotlin/domain/dtos/TestPlanRequestDTO.kt deleted file mode 100644 index 760a630..0000000 --- a/Melmac/src/main/kotlin/domain/dtos/TestPlanRequestDTO.kt +++ /dev/null @@ -1,6 +0,0 @@ -package dtos - -data class TestPlanRequestDTO( - val testName: String, - val metricMetricId: Int -) \ No newline at end of file diff --git a/Melmac/src/main/kotlin/domain/dtos/TestPlanVersionRequestDTO.kt b/Melmac/src/main/kotlin/domain/dtos/TestPlanVersionRequestDTO.kt index 7a48b6e..b405653 100644 --- a/Melmac/src/main/kotlin/domain/dtos/TestPlanVersionRequestDTO.kt +++ b/Melmac/src/main/kotlin/domain/dtos/TestPlanVersionRequestDTO.kt @@ -5,13 +5,13 @@ import dtos.TestMetricParameterRequestDTO data class TestPlanVersionRequestDTO( val notes: String?, val testName: String, - val metricMetricId: Int, + val metricName: String, val deviceName: String, val appName: String, val appVersion: String, val appPackage: String, val mainActivity: String? = null, - val executionTypeExecutionTypeId: Int, + val executionType: String, val thresholds: List, val metricParameters: List, val executionTypeParameters: List, diff --git a/Melmac/src/main/kotlin/domain/dtos/TestSuiteVersionPlanRequestDTO.kt b/Melmac/src/main/kotlin/domain/dtos/TestSuiteVersionPlanRequestDTO.kt deleted file mode 100644 index 4e41487..0000000 --- a/Melmac/src/main/kotlin/domain/dtos/TestSuiteVersionPlanRequestDTO.kt +++ /dev/null @@ -1,7 +0,0 @@ -package dtos - -data class TestSuiteVersionPlanRequestDTO( - val testSuiteVersionTestSuiteVersionId: Int, - val testPlanVersionTestPlanVersionId: Int, - val order: Int -) diff --git a/Melmac/src/main/kotlin/domain/dtos/TestSuiteVersionPlanResponseDTO.kt b/Melmac/src/main/kotlin/domain/dtos/TestSuiteVersionPlanResponseDTO.kt deleted file mode 100644 index d6cce01..0000000 --- a/Melmac/src/main/kotlin/domain/dtos/TestSuiteVersionPlanResponseDTO.kt +++ /dev/null @@ -1,7 +0,0 @@ -package dtos - -data class TestSuiteVersionPlanResponseDTO( - val testSuiteVersionTestSuiteVersionId: Int, - val testPlanVersionTestPlanVersionId: Int, - val order: Int -) diff --git a/Melmac/src/main/kotlin/domain/dtos/TestSuiteVersionRequestDTO.kt b/Melmac/src/main/kotlin/domain/dtos/TestSuiteVersionRequestDTO.kt deleted file mode 100644 index 39bda2b..0000000 --- a/Melmac/src/main/kotlin/domain/dtos/TestSuiteVersionRequestDTO.kt +++ /dev/null @@ -1,7 +0,0 @@ -package dtos - -data class TestSuiteVersionRequestDTO( - val version: String, - val notes: String?, - val testSuiteTestSuiteId: Int -) diff --git a/Melmac/src/main/kotlin/domain/dtos/TestSuiteVersionResponseDTO.kt b/Melmac/src/main/kotlin/domain/dtos/TestSuiteVersionResponseDTO.kt deleted file mode 100644 index cdce01c..0000000 --- a/Melmac/src/main/kotlin/domain/dtos/TestSuiteVersionResponseDTO.kt +++ /dev/null @@ -1,11 +0,0 @@ -package dtos - -import java.time.LocalDateTime - -data class TestSuiteVersionResponseDTO( - val testSuiteVersionId: Int, - val version: String, - val creationTimestamp: LocalDateTime, - val notes: String?, - val testSuiteTestSuiteId: Int -) diff --git a/Melmac/src/main/kotlin/domain/dtos/TestThresholdRequestDTO.kt b/Melmac/src/main/kotlin/domain/dtos/TestThresholdRequestDTO.kt index 4f1aab9..5595478 100644 --- a/Melmac/src/main/kotlin/domain/dtos/TestThresholdRequestDTO.kt +++ b/Melmac/src/main/kotlin/domain/dtos/TestThresholdRequestDTO.kt @@ -2,7 +2,7 @@ package dtos data class TestThresholdRequestDTO( val targetValue: Int, - val thresholdTypeThresholdTypeId: Int, + val thresholdType: String, val testPlanVersionTestPlanVersionId: Int, val metricOutputMetricOutputId: Int ) diff --git a/Melmac/src/main/kotlin/mappers/AppMapper.kt b/Melmac/src/main/kotlin/mappers/AppMapper.kt new file mode 100644 index 0000000..7e0f3da --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/AppMapper.kt @@ -0,0 +1,20 @@ +package mappers + +import domain.App +import dtos.AppResponseDTO + +object AppMapper { + fun toDto(app: App): AppResponseDTO { + return AppResponseDTO( + appId = app.appId ?: throw IllegalStateException("App ID cannot be null"), + appName = app.appName + ) + } + + fun toDomain(appResponseDTO: AppResponseDTO): App { + return App( + appId = appResponseDTO.appId, + appName = appResponseDTO.appName + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/AppVersionMapper.kt b/Melmac/src/main/kotlin/mappers/AppVersionMapper.kt new file mode 100644 index 0000000..9482db5 --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/AppVersionMapper.kt @@ -0,0 +1,22 @@ +package mappers + +import domain.AppVersion +import dtos.AppVersionResponseDTO + +object AppVersionMapper { + fun toDto(appVersion: AppVersion): AppVersionResponseDTO { + return AppVersionResponseDTO( + appVersionId = appVersion.appVersionId ?: throw IllegalStateException("AppVersion ID cannot be null"), + appId = appVersion.appId, + appVersion = appVersion.appVersion + ) + } + + fun toDomain(appVersionResponseDTO: AppVersionResponseDTO): AppVersion { + return AppVersion( + appVersionId = appVersionResponseDTO.appVersionId, + appId = appVersionResponseDTO.appId, + appVersion = appVersionResponseDTO.appVersion + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/AvailableDeviceMapper.kt b/Melmac/src/main/kotlin/mappers/AvailableDeviceMapper.kt new file mode 100644 index 0000000..f611392 --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/AvailableDeviceMapper.kt @@ -0,0 +1,25 @@ +package mappers + +import dtos.AvailableDeviceDTO +import domain.Device + +object AvailableDeviceMapper { + fun toDto(device: Device, osName: String, osVersion: String): AvailableDeviceDTO { + return AvailableDeviceDTO( + id = device.deviceId, + deviceName = device.deviceName, + deviceSerialNumber = device.deviceSerialNumber, + osName = osName, + osVersion = osVersion + ) + } + + fun toDomain(availableDeviceDTO: AvailableDeviceDTO, osVersionOsVersionId: Int): Device { + return Device( + deviceId = availableDeviceDTO.id, + deviceName = availableDeviceDTO.deviceName, + deviceSerialNumber = availableDeviceDTO.deviceSerialNumber, + osVersionOsVersionId = osVersionOsVersionId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/DeviceMapper.kt b/Melmac/src/main/kotlin/mappers/DeviceMapper.kt new file mode 100644 index 0000000..6f7384a --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/DeviceMapper.kt @@ -0,0 +1,24 @@ +package mappers + +import domain.Device +import dtos.DeviceResponseDTO + +object DeviceMapper { + fun toDto(device: Device): DeviceResponseDTO { + return DeviceResponseDTO( + deviceId = device.deviceId ?: throw IllegalStateException("Device ID cannot be null"), + deviceName = device.deviceName, + deviceSerialNumber = device.deviceSerialNumber, + osVersionOsVersionId = device.osVersionOsVersionId + ) + } + + fun toDomain(deviceResponseDTO: DeviceResponseDTO): Device { + return Device( + deviceId = deviceResponseDTO.deviceId, + deviceName = deviceResponseDTO.deviceName, + deviceSerialNumber = deviceResponseDTO.deviceSerialNumber, + osVersionOsVersionId = deviceResponseDTO.osVersionOsVersionId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/ExecutionTypeMapper.kt b/Melmac/src/main/kotlin/mappers/ExecutionTypeMapper.kt new file mode 100644 index 0000000..2dc3cc8 --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/ExecutionTypeMapper.kt @@ -0,0 +1,22 @@ +package mappers + +import domain.ExecutionType +import dtos.ExecutionTypeResponseDTO + +object ExecutionTypeMapper { + fun toDto(executionType: ExecutionType): ExecutionTypeResponseDTO { + return ExecutionTypeResponseDTO( + executionTypeId = executionType.executionTypeId ?: throw IllegalStateException("ExecutionType ID cannot be null"), + executionTypeName = executionType.executionTypeName, + executionTypeDescription = executionType.executionTypeDescription + ) + } + + fun toDomain(dto: ExecutionTypeResponseDTO): ExecutionType { + return ExecutionType( + executionTypeId = dto.executionTypeId, + executionTypeName = dto.executionTypeName, + executionTypeDescription = dto.executionTypeDescription + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/ExecutionTypeMetricMapper.kt b/Melmac/src/main/kotlin/mappers/ExecutionTypeMetricMapper.kt new file mode 100644 index 0000000..fa628f7 --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/ExecutionTypeMetricMapper.kt @@ -0,0 +1,20 @@ +package mappers + +import domain.ExecutionTypeMetric +import dtos.ExecutionTypeMetricResponseDTO + +object ExecutionTypeMetricMapper { + fun toDto(executionTypeMetric: ExecutionTypeMetric): ExecutionTypeMetricResponseDTO { + return ExecutionTypeMetricResponseDTO( + executionTypeExecutionTypeId = executionTypeMetric.executionTypeExecutionTypeId, + metricMetricId = executionTypeMetric.metricMetricId + ) + } + + fun toDomain(dto: ExecutionTypeMetricResponseDTO): ExecutionTypeMetric { + return ExecutionTypeMetric( + executionTypeExecutionTypeId = dto.executionTypeExecutionTypeId, + metricMetricId = dto.metricMetricId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/ExecutionTypeParameterMapper.kt b/Melmac/src/main/kotlin/mappers/ExecutionTypeParameterMapper.kt new file mode 100644 index 0000000..bc9ab2e --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/ExecutionTypeParameterMapper.kt @@ -0,0 +1,25 @@ +package mappers + +import domain.ExecutionTypeParameter +import dtos.ExecutionTypeParameterResponseDTO + +object ExecutionTypeParameterMapper { + fun toDto(executionTypeParameter: ExecutionTypeParameter): ExecutionTypeParameterResponseDTO { + return ExecutionTypeParameterResponseDTO( + executionTypeParameterId = executionTypeParameter.executionTypeParameterId + ?: throw IllegalStateException("ExecutionTypeParameter ID cannot be null"), + parameterName = executionTypeParameter.parameterName, + parameterType = executionTypeParameter.parameterType, + executionTypeExecutionTypeId = executionTypeParameter.executionTypeExecutionTypeId + ) + } + + fun toDomain(dto: ExecutionTypeParameterResponseDTO): ExecutionTypeParameter { + return ExecutionTypeParameter( + executionTypeParameterId = dto.executionTypeParameterId, + parameterName = dto.parameterName, + parameterType = dto.parameterType, + executionTypeExecutionTypeId = dto.executionTypeExecutionTypeId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/MetricMapper.kt b/Melmac/src/main/kotlin/mappers/MetricMapper.kt new file mode 100644 index 0000000..9829077 --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/MetricMapper.kt @@ -0,0 +1,20 @@ +package mappers + +import domain.Metric +import dtos.MetricResponseDTO + +object MetricMapper { + fun toDto(metric: Metric): MetricResponseDTO { + return MetricResponseDTO( + metricId = metric.metricId ?: throw IllegalStateException("Metric ID cannot be null"), + metricName = metric.metricName + ) + } + + fun toDomain(dto: MetricResponseDTO): Metric { + return Metric( + metricId = dto.metricId, + metricName = dto.metricName + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/MetricOutputMapper.kt b/Melmac/src/main/kotlin/mappers/MetricOutputMapper.kt new file mode 100644 index 0000000..e6978dc --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/MetricOutputMapper.kt @@ -0,0 +1,24 @@ +package mappers + +import domain.MetricOutput +import dtos.MetricOutputResponseDTO + +object MetricOutputMapper { + fun toDto(metricOutput: MetricOutput): MetricOutputResponseDTO { + return MetricOutputResponseDTO( + metricOutputId = metricOutput.metricOutputId ?: throw IllegalStateException("MetricOutput ID cannot be null"), + outputName = metricOutput.outputName, + unit = metricOutput.unit, + metricMetricId = metricOutput.metricMetricId + ) + } + + fun toDomain(dto: MetricOutputResponseDTO): MetricOutput { + return MetricOutput( + metricOutputId = dto.metricOutputId, + outputName = dto.outputName, + unit = dto.unit, + metricMetricId = dto.metricMetricId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/MetricParameterMapper.kt b/Melmac/src/main/kotlin/mappers/MetricParameterMapper.kt new file mode 100644 index 0000000..577e38c --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/MetricParameterMapper.kt @@ -0,0 +1,25 @@ +package mappers + +import domain.MetricParameter +import dtos.MetricParameterResponseDTO + +object MetricParameterMapper { + fun toDto(metricParameter: MetricParameter): MetricParameterResponseDTO { + return MetricParameterResponseDTO( + metricParameterId = metricParameter.metricParameterId + ?: throw IllegalStateException("MetricParameter ID cannot be null"), + parameterName = metricParameter.parameterName, + parameterType = metricParameter.parameterType, + metricMetricId = metricParameter.metricMetricId + ) + } + + fun toDomain(dto: MetricParameterResponseDTO): MetricParameter { + return MetricParameter( + metricParameterId = dto.metricParameterId, + parameterName = dto.parameterName, + parameterType = dto.parameterType, + metricMetricId = dto.metricMetricId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/OSVersionMapper.kt b/Melmac/src/main/kotlin/mappers/OSVersionMapper.kt new file mode 100644 index 0000000..20f01ae --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/OSVersionMapper.kt @@ -0,0 +1,22 @@ +package mappers + +import domain.OSVersion +import dtos.OSVersionResponseDTO + +object OSVersionMapper { + fun toDto(osVersion: OSVersion): OSVersionResponseDTO { + return OSVersionResponseDTO( + osVersionId = osVersion.osVersionId ?: throw IllegalStateException("OSVersion ID cannot be null"), + version = osVersion.version, + operativeSystemOperSysId = osVersion.operativeSystemOperSysId + ) + } + + fun toDomain(dto: OSVersionResponseDTO): OSVersion { + return OSVersion( + osVersionId = dto.osVersionId, + version = dto.version, + operativeSystemOperSysId = dto.operativeSystemOperSysId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/OperSysMapper.kt b/Melmac/src/main/kotlin/mappers/OperSysMapper.kt new file mode 100644 index 0000000..96208eb --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/OperSysMapper.kt @@ -0,0 +1,20 @@ +package mappers + +import domain.OperativeSystem +import dtos.OperativeSystemResponseDTO + +object OperSysMapper { + fun toDto(operativeSystem: OperativeSystem): OperativeSystemResponseDTO { + return OperativeSystemResponseDTO( + operSysId = operativeSystem.operSysId ?: throw IllegalStateException("OperSys ID cannot be null"), + operSysName = operativeSystem.operSysName + ) + } + + fun toDomain(dto: OperativeSystemResponseDTO): OperativeSystem { + return OperativeSystem( + operSysId = dto.operSysId, + operSysName = dto.operSysName + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/SuiteExecutionMapper.kt b/Melmac/src/main/kotlin/mappers/SuiteExecutionMapper.kt new file mode 100644 index 0000000..e55d682 --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/SuiteExecutionMapper.kt @@ -0,0 +1,25 @@ +package mappers + +import domain.SuiteExecution +import dtos.SuiteExecutionResponseDTO + +object SuiteExecutionMapper { + fun toDto(suiteExecution: SuiteExecution, executionResults: List): SuiteExecutionResponseDTO { + return SuiteExecutionResponseDTO( + suiteExecutionId = suiteExecution.suiteExecutionId ?: throw IllegalStateException("SuiteExecution ID cannot be null"), + initialTimestamp = suiteExecution.initialTimestamp, + endTimestamp = suiteExecution.endTimestamp, + testSuiteVersionTestSuiteVersionId = suiteExecution.testSuiteVersionTestSuiteVersionId, + executionResults = executionResults + ) + } + + fun toDomain(dto: SuiteExecutionResponseDTO): SuiteExecution { + return SuiteExecution( + suiteExecutionId = dto.suiteExecutionId, + initialTimestamp = dto.initialTimestamp, + endTimestamp = dto.endTimestamp, + testSuiteVersionTestSuiteVersionId = dto.testSuiteVersionTestSuiteVersionId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/TestExecutionMapper.kt b/Melmac/src/main/kotlin/mappers/TestExecutionMapper.kt new file mode 100644 index 0000000..0f35d83 --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/TestExecutionMapper.kt @@ -0,0 +1,62 @@ +package mappers + +import domain.TestExecution +import dtos.TestExecutionResponseDTO +import dtos.TestExecutionConfigDTO +import java.time.LocalDateTime + +object TestExecutionMapper { + fun toDto(testExecution: TestExecution): TestExecutionResponseDTO { + return TestExecutionResponseDTO( + testExecutionId = testExecution.testExecutionId ?: throw IllegalStateException("TestExecution ID cannot be null"), + initialTimestamp = testExecution.initialTimestamp, + endTimestamp = testExecution.endTimestamp, + passed = testExecution.passed, + testPlanVersionTestPlanVersionId = testExecution.testPlanVersionTestPlanVersionId + ) + } + + fun toDomain(dto: TestExecutionResponseDTO): TestExecution { + return TestExecution( + testExecutionId = dto.testExecutionId, + initialTimestamp = dto.initialTimestamp, + endTimestamp = dto.endTimestamp, + passed = dto.passed, + testPlanVersionTestPlanVersionId = dto.testPlanVersionTestPlanVersionId + ) + } + + /** + * Builds a TestExecutionConfigDTO from all required parameters. + * This mirrors the logic in your service. + */ + fun toConfigDto( + executionTypeName: String, + metricName: String, + metricParams: Map, + executionTypeParams: Map, + testThresholds: List>?, + deviceName: String, + deviceSerialNumber: String?, + platform: String, + appName: String, + appVersion: String, + appPackage: String, + mainActivity: String? + ): TestExecutionConfigDTO { + return TestExecutionConfigDTO( + executionTypeName = executionTypeName, + metricName = metricName, + metricParams = metricParams, + executionTypeParams = executionTypeParams, + testThresholds = testThresholds, + deviceName = deviceName, + deviceSerialNumber = deviceSerialNumber, + platform = platform, + appName = appName, + appVersion = appVersion, + appPackage = appPackage, + mainActivity = mainActivity + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/TestExecutionTypeParameterMapper.kt b/Melmac/src/main/kotlin/mappers/TestExecutionTypeParameterMapper.kt new file mode 100644 index 0000000..6045400 --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/TestExecutionTypeParameterMapper.kt @@ -0,0 +1,35 @@ +package mappers + +import domain.TestExecutionTypeParameter +import dtos.TestExecutionTypeParameterResponseDTO +import dtos.TestExecutionTypeParameterRequestDTO + +object TestExecutionTypeParameterMapper { + fun toDto(param: TestExecutionTypeParameter): TestExecutionTypeParameterResponseDTO { + return TestExecutionTypeParameterResponseDTO( + testExecutionTypeParameterId = param.testExecutionTypeParameterId + ?: throw IllegalStateException("TestExecutionTypeParameter ID cannot be null"), + parameterValue = param.parameterValue, + executionTypeParameterExecutionTypeParameterId = param.executionTypeParameterExecutionTypeParameterId, + testPlanVersionTestPlanVersionId = param.testPlanVersionTestPlanVersionId + ) + } + + fun toDomain(dto: TestExecutionTypeParameterResponseDTO): TestExecutionTypeParameter { + return TestExecutionTypeParameter( + testExecutionTypeParameterId = dto.testExecutionTypeParameterId, + parameterValue = dto.parameterValue, + executionTypeParameterExecutionTypeParameterId = dto.executionTypeParameterExecutionTypeParameterId, + testPlanVersionTestPlanVersionId = dto.testPlanVersionTestPlanVersionId + ) + } + + fun fromRequestDto(dto: TestExecutionTypeParameterRequestDTO, testPlanVersionId: Int, + executionTypeParameterId: Int): TestExecutionTypeParameter { + return TestExecutionTypeParameter( + parameterValue = dto.parameterValue, + executionTypeParameterExecutionTypeParameterId = executionTypeParameterId, + testPlanVersionTestPlanVersionId = testPlanVersionId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/TestMetricOutputResultMapper.kt b/Melmac/src/main/kotlin/mappers/TestMetricOutputResultMapper.kt new file mode 100644 index 0000000..9aeba93 --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/TestMetricOutputResultMapper.kt @@ -0,0 +1,25 @@ +package mappers + +import domain.TestMetricOutputResult +import dtos.TestMetricOutputResultResponseDTO + +object TestMetricOutputResultMapper { + fun toDto(result: TestMetricOutputResult): TestMetricOutputResultResponseDTO { + return TestMetricOutputResultResponseDTO( + testMetricOutputResultId = result.testMetricOutputResultId + ?: throw IllegalStateException("TestMetricOutputResult ID cannot be null"), + value = result.value, + metricOutputMetricOutputId = result.metricOutputMetricOutputId, + testExecutionTestExecutionId = result.testExecutionTestExecutionId + ) + } + + fun toDomain(dto: TestMetricOutputResultResponseDTO): TestMetricOutputResult { + return TestMetricOutputResult( + testMetricOutputResultId = dto.testMetricOutputResultId, + value = dto.value, + metricOutputMetricOutputId = dto.metricOutputMetricOutputId, + testExecutionTestExecutionId = dto.testExecutionTestExecutionId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/TestMetricParameterMapper.kt b/Melmac/src/main/kotlin/mappers/TestMetricParameterMapper.kt new file mode 100644 index 0000000..055cda3 --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/TestMetricParameterMapper.kt @@ -0,0 +1,35 @@ +package mappers + +import domain.TestMetricParameter +import dtos.TestMetricParameterResponseDTO +import dtos.TestMetricParameterRequestDTO + +object TestMetricParameterMapper { + fun toDto(param: TestMetricParameter): TestMetricParameterResponseDTO { + return TestMetricParameterResponseDTO( + testMetricParameterId = param.testMetricParameterId + ?: throw IllegalStateException("TestMetricParameter ID cannot be null"), + parameterValue = param.parameterValue, + metricParameterMetricParameterId = param.metricParameterMetricParameterId, + testPlanVersionTestPlanVersionId = param.testPlanVersionTestPlanVersionId + ) + } + + fun toDomain(dto: TestMetricParameterResponseDTO): TestMetricParameter { + return TestMetricParameter( + testMetricParameterId = dto.testMetricParameterId, + parameterValue = dto.parameterValue, + metricParameterMetricParameterId = dto.metricParameterMetricParameterId, + testPlanVersionTestPlanVersionId = dto.testPlanVersionTestPlanVersionId + ) + } + + fun fromRequestDto(dto: TestMetricParameterRequestDTO, testPlanVersionId: Int, + metricParameterId: Int): TestMetricParameter { + return TestMetricParameter( + parameterValue = dto.parameterValue, + metricParameterMetricParameterId = metricParameterId, + testPlanVersionTestPlanVersionId = testPlanVersionId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/TestPlanMapper.kt b/Melmac/src/main/kotlin/mappers/TestPlanMapper.kt new file mode 100644 index 0000000..360612e --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/TestPlanMapper.kt @@ -0,0 +1,22 @@ +package mappers + +import domain.TestPlan +import dtos.TestPlanResponseDTO + +object TestPlanMapper { + fun toDto(testPlan: TestPlan): TestPlanResponseDTO { + return TestPlanResponseDTO( + testPlanId = testPlan.testPlanId ?: throw IllegalStateException("TestPlan ID cannot be null"), + testName = testPlan.testName, + metricMetricId = testPlan.metricMetricId + ) + } + + fun toDomain(dto: TestPlanResponseDTO): TestPlan { + return TestPlan( + testPlanId = dto.testPlanId, + testName = dto.testName, + metricMetricId = dto.metricMetricId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/TestPlanVersionMapper.kt b/Melmac/src/main/kotlin/mappers/TestPlanVersionMapper.kt new file mode 100644 index 0000000..60074b7 --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/TestPlanVersionMapper.kt @@ -0,0 +1,47 @@ +package mappers + +import domain.TestPlanVersion +import dtos.* +import java.time.LocalDateTime + +object TestPlanVersionMapper { + fun toDto( + testPlanVersion: TestPlanVersion, + thresholds: List, + metricParameters: List, + executionTypeParameters: List, + testSuiteVersionId: Int + ): TestPlanVersionResponseDTO { + return TestPlanVersionResponseDTO( + testPlanVersionId = testPlanVersion.testPlanVersionId ?: throw IllegalStateException("TestPlanVersion ID cannot be null"), + version = testPlanVersion.version, + creationTimestamp = testPlanVersion.creationTimestamp, + notes = testPlanVersion.notes, + testPlanTestPlanId = testPlanVersion.testPlanTestPlanId, + deviceDeviceId = testPlanVersion.deviceDeviceId, + appVersionAppVersionId = testPlanVersion.appVersionAppVersionId, + appPackage = testPlanVersion.appPackage, + mainActivity = testPlanVersion.mainActivity, + executionTypeExecutionTypeId = testPlanVersion.executionTypeExecutionTypeId, + thresholds = thresholds, + metricParameters = metricParameters, + executionTypeParameters = executionTypeParameters, + testSuiteVersionId = testSuiteVersionId + ) + } + + fun toDomain(dto: TestPlanVersionResponseDTO): TestPlanVersion { + return TestPlanVersion( + testPlanVersionId = dto.testPlanVersionId, + version = dto.version, + creationTimestamp = dto.creationTimestamp, + notes = dto.notes, + appPackage = dto.appPackage, + mainActivity = dto.mainActivity, + testPlanTestPlanId = dto.testPlanTestPlanId, + deviceDeviceId = dto.deviceDeviceId, + appVersionAppVersionId = dto.appVersionAppVersionId, + executionTypeExecutionTypeId = dto.executionTypeExecutionTypeId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/TestSuiteMapper.kt b/Melmac/src/main/kotlin/mappers/TestSuiteMapper.kt new file mode 100644 index 0000000..1f408ef --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/TestSuiteMapper.kt @@ -0,0 +1,37 @@ +package mappers + +import domain.TestSuite +import dtos.TestSuiteResponseDTO +import dtos.TestSuiteRequestDTO +import java.time.LocalDateTime + +object TestSuiteMapper { + fun toDto(testSuite: TestSuite): TestSuiteResponseDTO { + return TestSuiteResponseDTO( + testSuiteId = testSuite.testSuiteId ?: throw IllegalStateException("TestSuite ID cannot be null"), + testSuiteName = testSuite.testSuiteName, + testSuiteDescription = testSuite.testSuiteDescription, + creationTimestamp = testSuite.creationTimestamp, + isActive = testSuite.isActive + ) + } + + fun toDomain(dto: TestSuiteResponseDTO): TestSuite { + return TestSuite( + testSuiteId = dto.testSuiteId, + testSuiteName = dto.testSuiteName, + testSuiteDescription = dto.testSuiteDescription, + creationTimestamp = dto.creationTimestamp, + isActive = dto.isActive + ) + } + + fun fromRequestDto(dto: TestSuiteRequestDTO, creationTimestamp: LocalDateTime, isActive: Boolean): TestSuite { + return TestSuite( + testSuiteName = dto.testSuiteName, + testSuiteDescription = dto.testSuiteDescription, + creationTimestamp = creationTimestamp, + isActive = isActive + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/TestThresholdMapper.kt b/Melmac/src/main/kotlin/mappers/TestThresholdMapper.kt new file mode 100644 index 0000000..d09361c --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/TestThresholdMapper.kt @@ -0,0 +1,37 @@ +package mappers + +import domain.TestThreshold +import dtos.TestThresholdResponseDTO +import dtos.TestThresholdRequestDTO + +object TestThresholdMapper { + fun toDto(threshold: TestThreshold): TestThresholdResponseDTO { + return TestThresholdResponseDTO( + testThresholdId = threshold.testThresholdId + ?: throw IllegalStateException("TestThreshold ID cannot be null"), + targetValue = threshold.targetValue, + thresholdTypeThresholdTypeId = threshold.thresholdTypeThresholdTypeId, + testPlanVersionTestPlanVersionId = threshold.testPlanVersionTestPlanVersionId, + metricOutputMetricOutputId = threshold.metricOutputMetricOutputId + ) + } + + fun toDomain(dto: TestThresholdResponseDTO): TestThreshold { + return TestThreshold( + testThresholdId = dto.testThresholdId, + targetValue = dto.targetValue, + thresholdTypeThresholdTypeId = dto.thresholdTypeThresholdTypeId, + testPlanVersionTestPlanVersionId = dto.testPlanVersionTestPlanVersionId, + metricOutputMetricOutputId = dto.metricOutputMetricOutputId + ) + } + + fun fromRequestDto(dto: TestThresholdRequestDTO, testPlanVersionId: Int, thresholdTypeId: Int): TestThreshold { + return TestThreshold( + targetValue = dto.targetValue, + thresholdTypeThresholdTypeId = thresholdTypeId, + testPlanVersionTestPlanVersionId = testPlanVersionId, + metricOutputMetricOutputId = dto.metricOutputMetricOutputId + ) + } +} \ No newline at end of file diff --git a/Melmac/src/main/kotlin/mappers/ThresholdTypeMapper.kt b/Melmac/src/main/kotlin/mappers/ThresholdTypeMapper.kt new file mode 100644 index 0000000..38327f4 --- /dev/null +++ b/Melmac/src/main/kotlin/mappers/ThresholdTypeMapper.kt @@ -0,0 +1,23 @@ +package mappers + +import domain.ThresholdType +import dtos.ThresholdTypeResponseDTO + +object ThresholdTypeMapper { + fun toDto(thresholdType: ThresholdType): ThresholdTypeResponseDTO { + return ThresholdTypeResponseDTO( + thresholdTypeId = thresholdType.thresholdTypeId + ?: throw IllegalStateException("ThresholdType ID cannot be null"), + thresholdTypeName = thresholdType.thresholdTypeName, + thresholdTypeDescription = thresholdType.thresholdTypeDescription + ) + } + + fun toDomain(dto: ThresholdTypeResponseDTO): ThresholdType { + return ThresholdType( + thresholdTypeId = dto.thresholdTypeId, + thresholdTypeName = dto.thresholdTypeName, + thresholdTypeDescription = dto.thresholdTypeDescription + ) + } +} diff --git a/Melmac/src/main/kotlin/repos/BootstrapUpdateRepository.kt b/Melmac/src/main/kotlin/repos/BootstrapUpdateRepository.kt new file mode 100644 index 0000000..9553128 --- /dev/null +++ b/Melmac/src/main/kotlin/repos/BootstrapUpdateRepository.kt @@ -0,0 +1,38 @@ +package repos + +import java.sql.Connection +import java.sql.ResultSet +import java.time.Instant +import repos.IRepos.IBootstrapUpdateRepository + +class BootstrapUpdateRepository(private val connection: Connection) : IBootstrapUpdateRepository { + + /** + * Returns the latest UpdateDate from the BootstrapUpdate table, or null if the table is empty. + */ + override fun getLatestUpdateDate(): Instant? { + val sql = "SELECT TOP 1 UpdateDate FROM BootstrapUpdate ORDER BY UpdateDate DESC" + connection.prepareStatement(sql).use { stmt -> + val rs: ResultSet = stmt.executeQuery() + return if (rs.next()) { + rs.getTimestamp("UpdateDate").toInstant() + } else { + null + } + } + } + + /** + * Saves a new update date to the BootstrapUpdate table. + * + * @param updateDate The Instant representing the update date to save. + * @return true if the operation was successful, false otherwise. + */ + override fun save(updateDate: Instant): Boolean { + val sql = "INSERT INTO BootstrapUpdate (UpdateDate) VALUES (?)" + connection.prepareStatement(sql).use { stmt -> + stmt.setTimestamp(1, java.sql.Timestamp.from(updateDate)) + return stmt.executeUpdate() > 0 + } + } +} diff --git a/Melmac/src/main/kotlin/repos/ExecutionTypeRepository.kt b/Melmac/src/main/kotlin/repos/ExecutionTypeRepository.kt index 1f3dc73..20799f4 100644 --- a/Melmac/src/main/kotlin/repos/ExecutionTypeRepository.kt +++ b/Melmac/src/main/kotlin/repos/ExecutionTypeRepository.kt @@ -79,8 +79,8 @@ class ExecutionTypeRepository(private val connection: Connection) : IExecutionTy SELECT et.ExecutionTypeID, et.ExecutionTypeName, et.ExecutionTypeDescription FROM ExecutionType et INNER JOIN ExecutionType_Metric etm ON etm.ExecutionTypeExecutionTypeID = et.ExecutionTypeID - WHERE etm.MetricMetricID = ? AND et.ExecutionTypeName = ? - """.trimIndent() + WHERE etm.MetricMetricID = ? AND LOWER(et.ExecutionTypeName) = LOWER(?) + """.trimIndent() val statement = connection.prepareStatement(query) statement.setInt(1, metricId) diff --git a/Melmac/src/main/kotlin/repos/IRepos/IBootstrapUpdateRepository.kt b/Melmac/src/main/kotlin/repos/IRepos/IBootstrapUpdateRepository.kt new file mode 100644 index 0000000..2796c9a --- /dev/null +++ b/Melmac/src/main/kotlin/repos/IRepos/IBootstrapUpdateRepository.kt @@ -0,0 +1,13 @@ +package repos.IRepos + +import java.time.Instant + +/** + * Interface for managing bootstrap update records in the database. + * + * Provides methods to retrieve the latest update date and save a new update date. + */ +interface IBootstrapUpdateRepository { + fun getLatestUpdateDate(): Instant? + fun save(updateDate: Instant): Boolean +} diff --git a/Melmac/src/main/kotlin/repos/MetricRepository.kt b/Melmac/src/main/kotlin/repos/MetricRepository.kt index d54a958..029885c 100644 --- a/Melmac/src/main/kotlin/repos/MetricRepository.kt +++ b/Melmac/src/main/kotlin/repos/MetricRepository.kt @@ -60,7 +60,7 @@ class MetricRepository(private val connection: Connection) : IMetricRepository { * @return The [Metric] if found, or null otherwise. */ override fun findByName(name: String): Metric? { - val query = "SELECT MetricID, MetricName FROM Metric WHERE MetricName = ?" + val query = "SELECT MetricID, MetricName FROM Metric WHERE LOWER(MetricName) = LOWER(?)" val statement = connection.prepareStatement(query) statement.setString(1, name) val resultSet = statement.executeQuery() diff --git a/Melmac/src/main/kotlin/repos/ThresholdTypeRepository.kt b/Melmac/src/main/kotlin/repos/ThresholdTypeRepository.kt index 704b104..4bff728 100644 --- a/Melmac/src/main/kotlin/repos/ThresholdTypeRepository.kt +++ b/Melmac/src/main/kotlin/repos/ThresholdTypeRepository.kt @@ -66,7 +66,7 @@ class ThresholdTypeRepository(private val connection: Connection) : IThresholdTy */ override fun findByName(name: String): ThresholdType? { val query = - "SELECT ThresholdTypeID, ThresholdTypeName, ThresholdTypeDescription FROM ThresholdType WHERE ThresholdTypeName = ?" + "SELECT ThresholdTypeID, ThresholdTypeName, ThresholdTypeDescription FROM ThresholdType WHERE LOWER(ThresholdTypeName) = LOWER(?)" val statement = connection.prepareStatement(query) statement.setString(1, name) val resultSet = statement.executeQuery() diff --git a/Melmac/src/main/kotlin/services/AppService.kt b/Melmac/src/main/kotlin/services/AppService.kt index c1997fa..22fb58d 100644 --- a/Melmac/src/main/kotlin/services/AppService.kt +++ b/Melmac/src/main/kotlin/services/AppService.kt @@ -1,5 +1,6 @@ package services +import domain.App import domain.AppVersion import dtos.AppResponseDTO import dtos.AppVersionResponseDTO @@ -9,6 +10,8 @@ import repos.IRepos.IAppRepository import repos.IRepos.IAppVersionRepository import services.IServices.IAppService import utils.Tools +import mappers.AppMapper +import mappers.AppVersionMapper /** * Service implementation for managing applications and their versions. @@ -32,12 +35,7 @@ class AppService( */ override fun getAllAppsFromDatabase(): List { val apps = appRepository.findAll() - return apps.map { app -> - AppResponseDTO( - appId = app.appId ?: throw IllegalStateException("App ID cannot be null"), - appName = app.appName - ) - } + return apps.map { app -> AppMapper.toDto(app) } } /** @@ -57,14 +55,7 @@ class AppService( app.appId ?: throw IllegalStateException("App ID cannot be null") ) - return versions.map { version: AppVersion -> - AppVersionResponseDTO( - appVersionId = version.appVersionId - ?: throw IllegalStateException("AppVersion ID cannot be null"), - appId = version.appId, - appVersion = version.appVersion - ) - } + return versions.map { version: AppVersion -> AppVersionMapper.toDto(version) } } /** @@ -79,10 +70,7 @@ class AppService( appRepository.findById(appId) ?: throw IllegalArgumentException("App with id '$appId' not found") - return AppResponseDTO( - appId = app.appId ?: throw IllegalStateException("App ID cannot be null"), - appName = app.appName - ) + return AppMapper.toDto(app) } /** @@ -97,12 +85,7 @@ class AppService( appVersionRepository.findById(appVersionId) ?: throw IllegalArgumentException("App Version with id '$appVersionId' not found") - return AppVersionResponseDTO( - appVersionId = appVersion.appVersionId - ?: throw IllegalStateException("AppVersion ID cannot be null"), - appId = appVersion.appId, - appVersion = appVersion.appVersion - ) + return AppVersionMapper.toDto(appVersion) } /** @@ -121,10 +104,7 @@ class AppService( appRepository.findById(appVersion.appId) ?: throw IllegalArgumentException("App with id '${appVersion.appId}' not found") - return AppResponseDTO( - appId = app.appId ?: throw IllegalStateException("App ID cannot be null"), - appName = app.appName - ) + return AppMapper.toDto(app) } // --- Folder Methods --- @@ -152,7 +132,7 @@ class AppService( val appNames = files.map { it.name }.distinct() return appNames.mapIndexed { index, appName -> - AppResponseDTO(appId = index + 1, appName = appName) + AppMapper.toDto(App(appId = index + 1, appName = appName)) } } @@ -186,7 +166,7 @@ class AppService( ) } - return AppResponseDTO(appId = 1, appName = appName) + return AppMapper.toDto(App(appId = 1, appName = appName)) } /** @@ -230,7 +210,13 @@ class AppService( } ?: "unknown" - AppVersionResponseDTO(appVersionId = index + 1, appId = index + 1, appVersion = version) + AppVersionMapper.toDto( + AppVersion( + appVersionId = index + 1, + appId = index + 1, + appVersion = version + ) + ) } } @@ -268,6 +254,12 @@ class AppService( ) } - return AppVersionResponseDTO(appVersionId = 1, appId = 1, appVersion = appVersion) + return AppVersionMapper.toDto( + AppVersion( + appVersionId = 1, + appId = 1, + appVersion = appVersion + ) + ) } } \ No newline at end of file diff --git a/Melmac/src/main/kotlin/services/DeviceService.kt b/Melmac/src/main/kotlin/services/DeviceService.kt index 5dc7315..c033447 100644 --- a/Melmac/src/main/kotlin/services/DeviceService.kt +++ b/Melmac/src/main/kotlin/services/DeviceService.kt @@ -8,6 +8,8 @@ import utils.Tools import repos.IRepos.IDeviceRepository import repos.IRepos.IOperSysVersionRepository import repos.IRepos.IOperSysRepository +import mappers.AvailableDeviceMapper +import domain.Device /** * Service implementation for managing device information. @@ -36,12 +38,10 @@ class DeviceService ( val os = osRepository.findById(osVersion.operativeSystemOperSysId) ?: return null - return AvailableDeviceDTO( - id = device.deviceId, - deviceName = device.deviceName, - deviceSerialNumber = device.deviceSerialNumber, - osName = os.operSysName, - osVersion = osVersion.version + return AvailableDeviceMapper.toDto( + device = device, + osName = os.operSysName, + osVersion = osVersion.version ) } @@ -148,13 +148,13 @@ class DeviceService ( if (available) { result.add( - AvailableDeviceDTO( - id = null, - deviceName = name, - deviceSerialNumber = udid, - osName = "iOS", - osVersion = version - ) + AvailableDeviceDTO( + id = null, + deviceName = name, + deviceSerialNumber = udid, + osName = "iOS", + osVersion = version + ) ) } } @@ -174,11 +174,11 @@ class DeviceService ( return avds.map { avdName -> val version = readAndroidAVDVersion(avdName) AvailableDeviceDTO( - id = null, - deviceName = avdName, - deviceSerialNumber = null, - osName = "Android", - osVersion = version + id = null, + deviceName = avdName, + deviceSerialNumber = null, + osName = "Android", + osVersion = version ) } } diff --git a/Melmac/src/main/kotlin/services/LoaderService.kt b/Melmac/src/main/kotlin/services/LoaderService.kt index 5b7e50d..6bef00c 100644 --- a/Melmac/src/main/kotlin/services/LoaderService.kt +++ b/Melmac/src/main/kotlin/services/LoaderService.kt @@ -7,6 +7,8 @@ import dtos.DataConfig import repos.IRepos.* import services.IServices.ILoaderService import java.io.File +import java.time.Instant +import java.time.format.DateTimeParseException /** * Service implementation for loading and synchronizing configuration data @@ -29,6 +31,7 @@ class LoaderService( private val metricOutputRepo: IMetricOutputRepository, private val executionTypeMetricRepo: IExecutionTypeMetricRepository, private val thresholdTypeRepo: IThresholdTypeRepository, + private val bootstrapUpdateRepo: IBootstrapUpdateRepository, private val configFilePath: String = "data.json" ) : ILoaderService { @@ -40,7 +43,22 @@ class LoaderService( override fun syncDataFromConfig() { val config = loadMetricsConfig() - // Load threshold types + val fileLastUpdated = try { + Instant.parse(config.lastUpdated) + } catch (e: DateTimeParseException) { + throw IllegalStateException("Invalid lastUpdated format in data.json: ${config.lastUpdated}") + } + + val dbLastUpdated = bootstrapUpdateRepo.getLatestUpdateDate() + + if (dbLastUpdated != null && !fileLastUpdated.isAfter(dbLastUpdated)) { + return + } + + if (dbLastUpdated == null || fileLastUpdated != dbLastUpdated) { + bootstrapUpdateRepo.save(fileLastUpdated) + } + config.thresholdTypes.forEach { configThresholdType -> val existingType = thresholdTypeRepo.findByName(configThresholdType.thresholdTypeName) if (existingType == null) { @@ -58,7 +76,6 @@ class LoaderService( } } - // Load metrics and related entities config.metrics.forEach { configMetric -> val existingMetric = metricRepo.findByName(configMetric.name) val dbMetricId = @@ -121,7 +138,6 @@ class LoaderService( existingExecTypeByName.executionTypeId!! } - // Ensure the ExecutionType is linked to the Metric in the join table executionTypeMetricRepo.link(dbMetricId, dbExecTypeId) execType.parameters.forEach { param -> diff --git a/Melmac/src/main/kotlin/services/MetricService.kt b/Melmac/src/main/kotlin/services/MetricService.kt index a7606b7..46fbe21 100644 --- a/Melmac/src/main/kotlin/services/MetricService.kt +++ b/Melmac/src/main/kotlin/services/MetricService.kt @@ -4,6 +4,11 @@ import domain.* import dtos.* import repos.IRepos.* import services.IServices.IMetricService +import mappers.MetricMapper +import mappers.MetricOutputMapper +import mappers.MetricParameterMapper +import mappers.ExecutionTypeMapper +import mappers.ExecutionTypeParameterMapper /** * Service implementation for managing metrics and their related entities. @@ -30,11 +35,7 @@ class MetricService( */ override fun getAllMetrics(): List { return metricRepository.findAll().map { metric -> - MetricResponseDTO( - metricId = metric.metricId - ?: throw IllegalStateException("Metric ID cannot be null"), - metricName = metric.metricName - ) + MetricMapper.toDto(metric) } } @@ -46,11 +47,7 @@ class MetricService( */ override fun getMetricById(id: Int): MetricResponseDTO? { val metric = metricRepository.findById(id) ?: return null - return MetricResponseDTO( - metricId = metric.metricId - ?: throw IllegalStateException("Metric ID cannot be null"), - metricName = metric.metricName - ) + return MetricMapper.toDto(metric) } /** @@ -61,16 +58,7 @@ class MetricService( */ override fun getOutputsByMetricId(metricId: Int): List { return metricOutputRepository.findByMetricId(metricId).map { output: MetricOutput -> - MetricOutputResponseDTO( - if (output.metricOutputId == null) { - throw IllegalStateException("MetricOutput ID cannot be null") - } else { - output.metricOutputId - }, - output.outputName, - output.unit, - output.metricMetricId - ) + MetricOutputMapper.toDto(output) } } @@ -82,15 +70,7 @@ class MetricService( */ override fun getParametersByMetricId(metricId: Int): List { return metricParameterRepository.findByMetricId(metricId).map { param -> - MetricParameterResponseDTO( - metricParameterId = param.metricParameterId - ?: throw IllegalStateException( - "MetricParameter ID cannot be null" - ), - parameterName = param.parameterName, - parameterType = param.parameterType, - metricMetricId = param.metricMetricId - ) + MetricParameterMapper.toDto(param) } } @@ -102,15 +82,7 @@ class MetricService( */ override fun getExecutionTypesByMetricId(metricId: Int): List { return executionTypeRepository.findByMetricId(metricId).map { execType: ExecutionType -> - ExecutionTypeResponseDTO( - if (execType.executionTypeId == null) { - throw IllegalStateException("ExecutionType ID cannot be null") - } else { - execType.executionTypeId - }, - execType.executionTypeName, - execType.executionTypeDescription - ) + ExecutionTypeMapper.toDto(execType) } } @@ -125,16 +97,7 @@ class MetricService( ): List { return executionTypeParameterRepository.findByExecutionTypeId(executionTypeId).map { param: ExecutionTypeParameter -> - ExecutionTypeParameterResponseDTO( - if (param.executionTypeParameterId == null) { - throw IllegalStateException("ExecutionTypeParameter ID cannot be null") - } else { - param.executionTypeParameterId - }, - param.parameterName, - param.parameterType, - param.executionTypeExecutionTypeId - ) + ExecutionTypeParameterMapper.toDto(param) } } } \ No newline at end of file diff --git a/Melmac/src/main/kotlin/services/TestExecutionService.kt b/Melmac/src/main/kotlin/services/TestExecutionService.kt index a9d5a42..07648a3 100644 --- a/Melmac/src/main/kotlin/services/TestExecutionService.kt +++ b/Melmac/src/main/kotlin/services/TestExecutionService.kt @@ -8,30 +8,12 @@ import java.time.Instant import java.time.ZoneId import repos.IRepos.* import services.IServices.ITestExecutionService +import mappers.TestExecutionMapper +import mappers.TestMetricOutputResultMapper /** * Service implementation for managing test executions. * Handles retrieval, execution, and result storage for test executions. - * - * @property testExecutionRepository Repository for TestExecution entities. - * @property testPlanVersionRepository Repository for TestPlanVersion entities. - * @property metricRepository Repository for Metric entities. - * @property metricOutputRepository Repository for MetricOutput entities. - * @property executionTypeRepository Repository for ExecutionType entities. - * @property deviceRepository Repository for Device entities. - * @property osVersionRepository Repository for OS version entities. - * @property osRepository Repository for OS entities. - * @property appVersionRepository Repository for AppVersion entities. - * @property appRepository Repository for App entities. - * @property testPlanExecutionTypeParamValueRepo Repository for ExecutionTypeParameter values. - * @property testPlanMetricParamValueRepo Repository for MetricParameter values. - * @property testPlanRepository Repository for TestPlan entities. - * @property metricParameterRepository Repository for MetricParameter entities. - * @property executionTypeParameterRepository Repository for ExecutionTypeParameter entities. - * @property testThresholdRepository Repository for Threshold entities. - * @property thresholdTypeRepository Repository for ThresholdType entities. - * @property testMetricOutputResultRepository Repository for TestMetricOutputResult entities. - * @property testRunner Test runner interface for executing tests. */ class TestExecutionService( private val testExecutionRepository: ITestExecutionRepository, @@ -44,8 +26,7 @@ class TestExecutionService( private val osRepository: IOperSysRepository, private val appVersionRepository: IAppVersionRepository, private val appRepository: IAppRepository, - private val testPlanExecutionTypeParamValueRepo: - ITestPlanExecutionTypeParameterValueRepository, + private val testPlanExecutionTypeParamValueRepo: ITestPlanExecutionTypeParameterValueRepository, private val testPlanMetricParamValueRepo: ITestPlanMetricParameterValueRepository, private val testPlanRepository: ITestPlanRepository, private val metricParameterRepository: IMetricParameterRepository, @@ -56,247 +37,157 @@ class TestExecutionService( private val testRunner: ITestRunner ) : ITestExecutionService { - /** - * Retrieves all test executions. - * - * @return List of [TestExecutionResponseDTO] representing all test executions. - */ - override fun getAllTestExecutions(): List { - return testExecutionRepository.findAll().map { - TestExecutionResponseDTO( - testExecutionId = it.testExecutionId!!, - initialTimestamp = it.initialTimestamp, - endTimestamp = it.endTimestamp, - passed = it.passed, - testPlanVersionTestPlanVersionId = - it.testPlanVersionTestPlanVersionId - ) - } + override fun getAllTestExecutions(): List { + return testExecutionRepository.findAll().map { + TestExecutionMapper.toDto(it) } - - /** - * Retrieves a test execution by its ID. - * - * @param id The ID of the test execution. - * @return [TestExecutionResponseDTO] for the test execution, or null if not found. - */ - override fun getTestExecutionById(id: Int): TestExecutionResponseDTO? { - val execution = testExecutionRepository.findById(id) ?: return null - return TestExecutionResponseDTO( - testExecutionId = execution.testExecutionId!!, - initialTimestamp = execution.initialTimestamp, - endTimestamp = execution.endTimestamp, - passed = execution.passed, - testPlanVersionTestPlanVersionId = - execution.testPlanVersionTestPlanVersionId + } + + override fun getTestExecutionById(id: Int): TestExecutionResponseDTO? { + val execution = testExecutionRepository.findById(id) ?: return null + return TestExecutionMapper.toDto(execution) + } + + override fun runTestExecution(testPlanVersionId: Int): TestExecutionResponseDTO { + val testPlanVersion = + testPlanVersionRepository.findById(testPlanVersionId) + ?: throw IllegalStateException("TestPlanVersion with ID $testPlanVersionId not found") + + val testPlan = + testPlanRepository.findById(testPlanVersion.testPlanTestPlanId) + ?: throw IllegalStateException("TestPlan ${testPlanVersion.testPlanTestPlanId} not found") + + val metric = + metricRepository.findById(testPlan.metricMetricId) + ?: throw IllegalStateException("Metric ${testPlan.metricMetricId} not found") + + val executionType = + executionTypeRepository.findById(testPlanVersion.executionTypeExecutionTypeId) + ?: throw IllegalStateException("ExecutionType ${testPlanVersion.executionTypeExecutionTypeId} not found") + + val device = + deviceRepository.findById(testPlanVersion.deviceDeviceId) + ?: throw IllegalStateException("Device ${testPlanVersion.deviceDeviceId} not found") + + val os = + osRepository.findById(device.osVersionOsVersionId) + ?: throw IllegalStateException("OS ${device.osVersionOsVersionId} not found") + + val appVersion = + appVersionRepository.findById(testPlanVersion.appVersionAppVersionId) + ?: throw IllegalStateException("AppVersion ${testPlanVersion.appVersionAppVersionId} not found") + + val app = + appRepository.findById(appVersion.appId) + ?: throw IllegalStateException("App ${appVersion.appId} not found") + + val execTypeParamsValues = + testPlanExecutionTypeParamValueRepo.findByTestPlanVersionId(testPlanVersionId) + val metricParamsValues = + testPlanMetricParamValueRepo.findByTestPlanVersionId(testPlanVersionId) + + val execTypeParams = + execTypeParamsValues.mapNotNull { paramValue -> + executionTypeParameterRepository.findById( + paramValue.executionTypeParameterExecutionTypeParameterId ) - } - - /** - * Executes a test plan version and stores the results. - * - * @param testPlanVersionId The ID of the test plan version to execute. - * @return [TestExecutionResponseDTO] containing the execution result. - * @throws IllegalStateException if any required entity is not found. - */ - override fun runTestExecution(testPlanVersionId: Int): TestExecutionResponseDTO { - val testPlanVersion = - testPlanVersionRepository.findById(testPlanVersionId) - ?: throw IllegalStateException( - "TestPlanVersion with ID $testPlanVersionId not found" - ) - - val testPlan = - testPlanRepository.findById(testPlanVersion.testPlanTestPlanId) - ?: throw IllegalStateException( - "TestPlan ${testPlanVersion.testPlanTestPlanId} not found" - ) - - val metric = - metricRepository.findById(testPlan.metricMetricId) - ?: throw IllegalStateException( - "Metric ${testPlan.metricMetricId} not found" - ) - - val executionType = - executionTypeRepository.findById( - testPlanVersion.executionTypeExecutionTypeId - ) - ?: throw IllegalStateException( - "ExecutionType ${testPlanVersion.executionTypeExecutionTypeId} not found" - ) - - val device = - deviceRepository.findById(testPlanVersion.deviceDeviceId) - ?: throw IllegalStateException( - "Device ${testPlanVersion.deviceDeviceId} not found" - ) - - val os = - osRepository.findById(device.osVersionOsVersionId) - ?: throw IllegalStateException( - "OS ${device.osVersionOsVersionId} not found" - ) - - val appVersion = - appVersionRepository.findById(testPlanVersion.appVersionAppVersionId) - ?: throw IllegalStateException( - "AppVersion ${testPlanVersion.appVersionAppVersionId} not found" - ) - - val app = - appRepository.findById(appVersion.appId) - ?: throw IllegalStateException("App ${appVersion.appId} not found") - - val execTypeParamsValues = - testPlanExecutionTypeParamValueRepo.findByTestPlanVersionId( - testPlanVersionId - ) - val metricParamsValues = - testPlanMetricParamValueRepo.findByTestPlanVersionId(testPlanVersionId) - - val execTypeParams = - execTypeParamsValues.mapNotNull { paramValue -> - executionTypeParameterRepository.findById( - paramValue.executionTypeParameterExecutionTypeParameterId - ) - } - - val metricParams = - metricParamsValues.mapNotNull { paramValue -> - metricParameterRepository.findById( - paramValue.metricParameterMetricParameterId - ) - } + } - val metricOutputs = - metricOutputRepository.findByMetricId( - metric.metricId - ?: throw IllegalStateException("Metric ID cannot be null") - ) - - val thresholds = - testThresholdRepository.findByTestPlanVersionId(testPlanVersionId).map { - threshold -> - val thresholdType = - thresholdTypeRepository.findById( - threshold.thresholdTypeThresholdTypeId - ) - ?: throw IllegalStateException( - "ThresholdType ${threshold.thresholdTypeThresholdTypeId} not found" - ) - val metricOutput = - metricOutputs.find { - it.metricOutputId == - threshold.metricOutputMetricOutputId - } - ?: throw IllegalStateException( - "MetricOutput ${threshold.metricOutputMetricOutputId} not found" - ) - Triple( - threshold.targetValue.toString(), - thresholdType.thresholdTypeName, - metricOutput.outputName ?: "" - ) - } - - val configDTO = - TestExecutionConfigDTO( - executionTypeName = executionType.executionTypeName, - metricName = metric.metricName, - metricParams = - metricParams.associate { metricParam -> - val paramValue = - metricParamsValues.firstOrNull { - it.metricParameterMetricParameterId == - metricParam - .metricParameterId - } - metricParam.parameterName to - (paramValue?.parameterValue ?: "") - }, - executionTypeParams = - execTypeParams.associate { execTypeParam -> - val paramValue = - execTypeParamsValues.firstOrNull { - it.executionTypeParameterExecutionTypeParameterId == - execTypeParam - .executionTypeParameterId - } - execTypeParam.parameterName to - (paramValue?.parameterValue ?: "") - }, - testThresholds = - thresholds.takeIf { it.isNotEmpty() }?.map { triple -> - Triple( - triple.first, - triple.second, - triple.third - ) - }, - deviceName = device.deviceName, - deviceSerialNumber = device.deviceSerialNumber, - platform = os.operSysName, - appName = app.appName, - appVersion = appVersion.appVersion, - appPackage = testPlanVersion.appPackage, - mainActivity = testPlanVersion.mainActivity, - ) - - val start = - Instant.ofEpochMilli(System.currentTimeMillis()) - .atZone(ZoneId.systemDefault()) - .toLocalDateTime() - - // Call the test runner and expect it to return a map with at least "success" and - // "value" - val resultOutputs = testRunner.run(configDTO) - - val end = - Instant.ofEpochMilli(System.currentTimeMillis()) - .atZone(ZoneId.systemDefault()) - .toLocalDateTime() - - // Use the "success" field from the test output, default to false if missing - val passed = resultOutputs["success"]?.toBoolean() ?: false - - val testExecution = - TestExecution( - testExecutionId = null, - testPlanVersionTestPlanVersionId = testPlanVersion.testPlanVersionId - ?: throw IllegalStateException( - "TestPlanVersionId cannot be null" - ), - initialTimestamp = start, - endTimestamp = end, - passed = passed.toString() - ) - val testExecutionId = testExecutionRepository.save(testExecution) - - (metricOutputs as Iterable).forEach { output -> - val outputId = - output.metricOutputId - ?: throw IllegalStateException( - "MetricOutput ID cannot be null" - ) - val value = resultOutputs[output.outputName] ?: "" - testMetricOutputResultRepository.save( - TestMetricOutputResult( - testMetricOutputResultId = null, - testExecutionTestExecutionId = testExecutionId, - metricOutputMetricOutputId = outputId, - value = value, - ) - ) - } - - return TestExecutionResponseDTO( - testExecutionId = testExecutionId, - initialTimestamp = testExecution.initialTimestamp, - endTimestamp = testExecution.endTimestamp, - passed = testExecution.passed, - testPlanVersionTestPlanVersionId = - testExecution.testPlanVersionTestPlanVersionId + val metricParams = + metricParamsValues.mapNotNull { paramValue -> + metricParameterRepository.findById( + paramValue.metricParameterMetricParameterId ) + } + + val metricOutputs = + metricOutputRepository.findByMetricId( + metric.metricId ?: throw IllegalStateException("Metric ID cannot be null") + ) + + val thresholds = + testThresholdRepository.findByTestPlanVersionId(testPlanVersionId).map { threshold -> + val thresholdType = + thresholdTypeRepository.findById(threshold.thresholdTypeThresholdTypeId) + ?: throw IllegalStateException("ThresholdType ${threshold.thresholdTypeThresholdTypeId} not found") + val metricOutput = + metricOutputs.find { it.metricOutputId == threshold.metricOutputMetricOutputId } + ?: throw IllegalStateException("MetricOutput ${threshold.metricOutputMetricOutputId} not found") + Triple( + threshold.targetValue.toString(), + thresholdType.thresholdTypeName, + metricOutput.outputName ?: "" + ) + } + + val configDTO = + TestExecutionMapper.toConfigDto( + executionTypeName = executionType.executionTypeName, + metricName = metric.metricName, + metricParams = metricParams.associate { metricParam -> + val paramValue = metricParamsValues.firstOrNull { + it.metricParameterMetricParameterId == metricParam.metricParameterId + } + metricParam.parameterName to (paramValue?.parameterValue ?: "") + }, + executionTypeParams = execTypeParams.associate { execTypeParam -> + val paramValue = execTypeParamsValues.firstOrNull { + it.executionTypeParameterExecutionTypeParameterId == execTypeParam.executionTypeParameterId + } + execTypeParam.parameterName to (paramValue?.parameterValue ?: "") + }, + testThresholds = thresholds.takeIf { it.isNotEmpty() }?.map { triple -> + Triple(triple.first, triple.second, triple.third) + }, + deviceName = device.deviceName, + deviceSerialNumber = device.deviceSerialNumber, + platform = os.operSysName, + appName = app.appName, + appVersion = appVersion.appVersion, + appPackage = testPlanVersion.appPackage, + mainActivity = testPlanVersion.mainActivity, + ) + + val start = + Instant.ofEpochMilli(System.currentTimeMillis()) + .atZone(ZoneId.systemDefault()) + .toLocalDateTime() + + val resultOutputs = testRunner.run(configDTO) + + val end = + Instant.ofEpochMilli(System.currentTimeMillis()) + .atZone(ZoneId.systemDefault()) + .toLocalDateTime() + + val passed = resultOutputs["success"]?.toBoolean() ?: false + + val testExecution = TestExecution( + testExecutionId = null, + testPlanVersionTestPlanVersionId = testPlanVersion.testPlanVersionId + ?: throw IllegalStateException("TestPlanVersionId cannot be null"), + initialTimestamp = start, + endTimestamp = end, + passed = passed.toString() + ) + val testExecutionId = testExecutionRepository.save(testExecution) + + (metricOutputs as Iterable).forEach { output -> + val outputId = output.metricOutputId + ?: throw IllegalStateException("MetricOutput ID cannot be null") + val value = resultOutputs[output.outputName] ?: "" + testMetricOutputResultRepository.save( + TestMetricOutputResult( + testMetricOutputResultId = null, + testExecutionTestExecutionId = testExecutionId, + metricOutputMetricOutputId = outputId, + value = value, + ) + ) } + + return TestExecutionMapper.toDto( + testExecution.copy(testExecutionId = testExecutionId) + ) + } } \ No newline at end of file diff --git a/Melmac/src/main/kotlin/services/TestMetricOutputResultService.kt b/Melmac/src/main/kotlin/services/TestMetricOutputResultService.kt index 11ee4a8..12416f2 100644 --- a/Melmac/src/main/kotlin/services/TestMetricOutputResultService.kt +++ b/Melmac/src/main/kotlin/services/TestMetricOutputResultService.kt @@ -4,6 +4,7 @@ import domain.TestMetricOutputResult import dtos.TestMetricOutputResultResponseDTO import repos.IRepos.ITestMetricOutputResultRepository import services.IServices.ITestMetricOutputResultService +import mappers.TestMetricOutputResultMapper /** * Service implementation for managing test metric output results. @@ -22,7 +23,7 @@ class TestMetricOutputResultService( */ override suspend fun getAll(): List = repo.findAll().map { outputResult: TestMetricOutputResult -> - toResponse(outputResult) + TestMetricOutputResultMapper.toDto(outputResult) } /** @@ -33,22 +34,6 @@ class TestMetricOutputResultService( */ override suspend fun getByExecutionId(testExecutionId: Int): List = repo.getByExecutionId(testExecutionId).map { outputResult: TestMetricOutputResult -> - toResponse(outputResult) + TestMetricOutputResultMapper.toDto(outputResult) } - - /** - * Converts a [TestMetricOutputResult] entity to a [TestMetricOutputResultResponseDTO]. - * - * @param outputResult The entity to convert. - * @return The corresponding DTO. - * @throws IllegalArgumentException if the entity's ID is null. - */ - private fun toResponse(outputResult: TestMetricOutputResult): TestMetricOutputResultResponseDTO { - return TestMetricOutputResultResponseDTO( - testMetricOutputResultId = outputResult.testMetricOutputResultId ?: throw IllegalArgumentException("testMetricOutputResultId is null"), - value = outputResult.value, - metricOutputMetricOutputId = outputResult.metricOutputMetricOutputId, - testExecutionTestExecutionId = outputResult.testExecutionTestExecutionId - ) - } } \ No newline at end of file diff --git a/Melmac/src/main/kotlin/services/TestPlanService.kt b/Melmac/src/main/kotlin/services/TestPlanService.kt index dfa7a9c..d8f9c44 100644 --- a/Melmac/src/main/kotlin/services/TestPlanService.kt +++ b/Melmac/src/main/kotlin/services/TestPlanService.kt @@ -3,21 +3,26 @@ package services import domain.* import dtos.* import java.time.LocalDateTime +import mappers.TestExecutionTypeParameterMapper +import mappers.TestMetricParameterMapper +import mappers.TestPlanVersionMapper +import mappers.TestThresholdMapper import repos.IRepos.* import services.IServices.IAppService import services.IServices.IDeviceService import services.IServices.ITestPlanService /** - * Service implementation for managing test plans and their versions. - * Handles creation, retrieval, and association of test plans, devices, apps, parameters, and thresholds. + * Service implementation for managing test plans and their versions. Handles creation, retrieval, + * and association of test plans, devices, apps, parameters, and thresholds. * * @property testPlanRepository Repository for TestPlan entities. * @property testPlanVersionRepository Repository for TestPlanVersion entities. * @property testSuiteRepository Repository for TestSuite entities. * @property testThresholdRepository Repository for Threshold entities. * @property testPlanMetricParameterRepository Repository for TestPlanMetricParameterValue entities. - * @property testPlanExecutionTypeParameterRepository Repository for TestPlanExecutionTypeParameterValue entities. + * @property testPlanExecutionTypeParameterRepository Repository for + * TestPlanExecutionTypeParameterValue entities. * @property testSuiteVersionPlanRepository Repository for TestSuiteVersionPlan entities. * @property deviceRepository Repository for Device entities. * @property appRepository Repository for App entities. @@ -26,6 +31,9 @@ import services.IServices.ITestPlanService * @property osVersionRepository Repository for OSVersion entities. * @property deviceService Service for device-related operations. * @property appService Service for app-related operations. + * @property metricRepository Repository for Metric entities. + * @property thresholdTypeRepository Repository for ThresholdType entities. + * @property executionTypeRepository Repository for ExecutionType entities. */ class TestPlanService( private val testPlanRepository: ITestPlanRepository, @@ -43,6 +51,11 @@ class TestPlanService( private val osVersionRepository: IOperSysVersionRepository, private val deviceService: IDeviceService, private val appService: IAppService, + private val metricRepository: IMetricRepository, + private val thresholdTypeRepository: IThresholdTypeRepository, + private val executionTypeRepository: IExecutionTypeRepository, + private val metricParameterRepository: IMetricParameterRepository, + private val executionTypeParameterRepository: IExecutionTypeParameterRepository ) : ITestPlanService { /** @@ -64,11 +77,13 @@ class TestPlanService( } /** - * Creates a new test plan and its version, including all related entities such as device, app, app version, - * thresholds, metric parameters, execution type parameters, and suite associations. + * Creates a new test plan and its version, including all related entities such as device, + * app, app version, thresholds, metric parameters, execution type parameters, and suite + * associations. * * @param request The [TestPlanVersionRequestDTO] containing all required information. - * @return [TestPlanVersionResponseDTO] representing the created test plan version and its associations. + * @return [TestPlanVersionResponseDTO] representing the created test plan version and its + * associations. * @throws IllegalArgumentException if required entities are not found or invalid. * @throws IllegalStateException if required IDs are missing after creation. */ @@ -76,141 +91,265 @@ class TestPlanService( request: TestPlanVersionRequestDTO ): TestPlanVersionResponseDTO { println("Starting createTestPlanWithVersion") + val metric = getMetric(request.metricName) + val testPlanId = createTestPlan(request, metric) + val device = getDevice(request.deviceName) + val os = getOrCreateOS(device.osName) + val osVersion = getOrCreateOSVersion(os, device.osVersion) + val databaseDevice = getOrCreateDevice(device, os, osVersion) + val app = getOrCreateApp(request.appName) + val appVersionDef = getOrCreateAppVersion(app, request.appVersion) + val executionType = getExecutionType(request.executionType) + val savedTestPlanVersion = + createTestPlanVersion( + request, + testPlanId, + databaseDevice, + appVersionDef, + executionType + ) + val savedThresholds = saveThresholds(request, savedTestPlanVersion) + val savedMetricParameters = + saveMetricParameters(request, savedTestPlanVersion, metric) + val savedExecutionTypeParameters = + saveExecutionTypeParameters(request, savedTestPlanVersion) + saveTestSuiteVersionPlan(request, savedTestPlanVersion) + return TestPlanVersionMapper.toDto( + savedTestPlanVersion, + savedThresholds.map { TestThresholdMapper.toDto(it) }, + savedMetricParameters.map { TestMetricParameterMapper.toDto(it) }, + savedExecutionTypeParameters.map { + TestExecutionTypeParameterMapper.toDto(it) + }, + request.testSuiteVersionId + ) + } + + /** + * Retrieves a [Metric] entity by its name. + * + * @param metricName The name of the metric. + * @return The [Metric] entity. + * @throws IllegalArgumentException if the metric is not found. + */ + private fun getMetric(metricName: String): Metric { + return metricRepository.findByName(metricName) + ?: throw IllegalArgumentException("Metric not found") + } + + /** + * Creates a new [TestPlan] entity. + * + * @param request The [TestPlanVersionRequestDTO] containing test plan details. + * @param metric The [Metric] associated with the test plan. + * @return The ID of the newly created test plan. + * @throws IllegalStateException if the metric ID is null. + */ + private fun createTestPlan(request: TestPlanVersionRequestDTO, metric: Metric): Int { val newTestPlan = TestPlan( testPlanId = null, testName = request.testName, - metricMetricId = request.metricMetricId + metricMetricId = metric.metricId + ?: throw IllegalStateException( + "Metric ID cannot be null" + ) ) println("Saving new TestPlan: $newTestPlan") - val testPlanId = testPlanRepository.save(newTestPlan) - println("Saved TestPlan with ID: $testPlanId") + return testPlanRepository.save(newTestPlan) + } - val deviceName = request.deviceName + /** + * Retrieves a device by its name. + * + * @param deviceName The name of the device. + * @return [AvailableDeviceDTO] for the device. + * @throws IllegalArgumentException if the device is not found. + */ + private fun getDevice(deviceName: String): AvailableDeviceDTO { println("Looking up device by name: $deviceName") - val device = - deviceService.getDeviceByName(deviceName) - ?: throw IllegalArgumentException("Device not found") - println("Found device: $device") + return deviceService.getDeviceByName(deviceName) + ?: throw IllegalArgumentException("Device not found") + } - println("Looking up OS by name: ${device.osName}") - val os = - osRepository.findByName(device.osName) - ?: OperativeSystem( - operSysId = - osRepository.save( - OperativeSystem( - operSysId = null, - operSysName = device.osName - ) - ), - operSysName = device.osName - ) - println("Using OS: $os") + /** + * Retrieves or creates an [OperativeSystem] entity by its name. + * + * @param osName The name of the operating system. + * @return The [OperativeSystem] entity. + */ + private fun getOrCreateOS(osName: String): OperativeSystem { + println("Looking up OS by name: $osName") + return osRepository.findByName(osName) + ?: OperativeSystem( + operSysId = + osRepository.save( + OperativeSystem( + operSysId = null, + operSysName = osName + ) + ), + operSysName = osName + ) + } + /** + * Retrieves or creates an [OSVersion] entity for a given OS. + * + * @param os The [OperativeSystem] entity. + * @param osVersionName The version name. + * @return The [OSVersion] entity. + * @throws IllegalStateException if the OS ID is null. + */ + private fun getOrCreateOSVersion(os: OperativeSystem, osVersionName: String): OSVersion { val operSysId = os.operSysId ?: throw IllegalStateException("OS ID cannot be null") println("Looking up OS versions for OS ID: $operSysId") val osVersions = osVersionRepository.findByOperSysId(operSysId) - println("Found OS versions: $osVersions") + return if (osVersions.isNotEmpty()) { + println("Using existing OS version: ${osVersions.first()}") + osVersions.first() + } else { + println("Creating new OS version for device: $osVersionName") + val newOsVersion = + OSVersion( + osVersionId = null, + version = osVersionName, + operativeSystemOperSysId = operSysId + ) + val savedOsVersionId = osVersionRepository.save(newOsVersion) + println("Saved new OS version with ID: $savedOsVersionId") + newOsVersion.copy(osVersionId = savedOsVersionId) + } + } - val osVersion = - if (osVersions.isNotEmpty()) { - println("Using existing OS version: ${osVersions.first()}") - osVersions.first() - } else { - println("Creating new OS version for device: ${device.osVersion}") - val newOsVersion = - OSVersion( - osVersionId = null, - version = device.osVersion, - operativeSystemOperSysId = operSysId + /** + * Retrieves or creates a [Device] entity. + * + * @param device The [AvailableDeviceDTO] containing device details. + * @param os The [OperativeSystem] entity. + * @param osVersion The [OSVersion] entity. + * @return The [Device] entity. + * @throws IllegalArgumentException if required device details are missing. + * @throws IllegalStateException if the OS Version ID is null. + */ + private fun getOrCreateDevice( + device: AvailableDeviceDTO, + os: OperativeSystem, + osVersion: OSVersion + ): Device { + return if (os.operSysName.equals("ios", ignoreCase = true)) { + deviceRepository.findBySerialNumber( + device.deviceSerialNumber + ?: throw IllegalArgumentException( + "Device serial number cannot be null" ) - val savedOsVersionId = osVersionRepository.save(newOsVersion) - println("Saved new OS version with ID: $savedOsVersionId") - newOsVersion.copy(osVersionId = savedOsVersionId) - } - - val databaseDevice = - if (os.operSysName.equals("ios", ignoreCase = true)) { - deviceRepository.findBySerialNumber( - device.deviceSerialNumber - ?: throw IllegalArgumentException( - "Device serial number cannot be null" - ) - ) - } else { - deviceRepository.findByName(device.deviceName) + ) + } else { + deviceRepository.findByName(device.deviceName) + } + ?: run { + println("Device not found in DB, creating new device...") + val newDevice = + Device( + deviceId = null, + deviceName = device.deviceName, + deviceSerialNumber = device.deviceSerialNumber, + osVersionOsVersionId = osVersion.osVersionId + ?: throw IllegalStateException( + "OS Version ID cannot be null" + ) + ) + val savedDeviceId = deviceRepository.save(newDevice) + println("Saved new device with ID: $savedDeviceId") + newDevice.copy(deviceId = savedDeviceId) } - ?: run { - println("Device not found in DB, creating new device...") - val newDevice = - Device( - deviceId = null, - deviceName = device.deviceName, - deviceSerialNumber = - device.deviceSerialNumber, - osVersionOsVersionId = osVersion.osVersionId - ?: throw IllegalStateException( - "OS Version ID cannot be null" - ) - ) - val savedDeviceId = deviceRepository.save(newDevice) - println("Saved new device with ID: $savedDeviceId") - newDevice.copy(deviceId = savedDeviceId) - } + } - val appName = request.appName + /** + * Retrieves or creates an [App] entity by its name. + * + * @param appName The name of the app. + * @return The [App] entity. + */ + private fun getOrCreateApp(appName: String): App { println("Looking up app by name: $appName") - val app = - appRepository.findByName(appName) - ?: run { - println("App not found in DB, looking in folder...") - val appInFolderDto = - appService.getAppByNameFromFolder(appName) - val appInFolder = - App( - appId = null, - appName = appInFolderDto.appName, - ) - val newAppId = appRepository.save(appInFolder) - println("Saved new app with ID: $newAppId") - appInFolder.copy(appId = newAppId) - } - println("Using app: $app") + return appRepository.findByName(appName) + ?: run { + println("App not found in DB, looking in folder...") + val appInFolderDto = appService.getAppByNameFromFolder(appName) + val appInFolder = + App(appId = null, appName = appInFolderDto.appName) + val newAppId = appRepository.save(appInFolder) + println("Saved new app with ID: $newAppId") + appInFolder.copy(appId = newAppId) + } + } - val appVersion = request.appVersion + /** + * Retrieves or creates an [AppVersion] entity for a given app. + * + * @param app The [App] entity. + * @param appVersion The version string. + * @return The [AppVersion] entity. + * @throws IllegalArgumentException if the app version is not found in the folder. + */ + private fun getOrCreateAppVersion(app: App, appVersion: String): AppVersion { println("Looking up app version: $appVersion for appId: ${app.appId}") val existingAppVersion = appVersionRepository.findByAppIdAndVersion(app.appId!!, appVersion) - val appVersionDef = - if (existingAppVersion != null) { - println("Found existing app version: $existingAppVersion") - existingAppVersion - } else { - println("App version not found in DB, looking in folder...") - val appVersionInFolderDto = - appService.getAppVersionByNameFromFolder( - app.appName, - appVersion - ) - if (appVersionInFolderDto.appVersion.isEmpty()) { - throw IllegalArgumentException( - "App version not found in folder" - ) - } - val newAppVersion = - AppVersion( - appVersionId = null, - appId = app.appId, - appVersion = appVersionInFolderDto.appVersion - ) - val savedAppVersionId = appVersionRepository.save(newAppVersion) - println("Saved new app version with ID: $savedAppVersionId") - newAppVersion.copy(appVersionId = savedAppVersionId) + return if (existingAppVersion != null) { + println("Found existing app version: $existingAppVersion") + existingAppVersion + } else { + println("App version not found in DB, looking in folder...") + val appVersionInFolderDto = + appService.getAppVersionByNameFromFolder(app.appName, appVersion) + if (appVersionInFolderDto.appVersion.isEmpty()) { + throw IllegalArgumentException("App version not found in folder") } - println("Using app version: $appVersionDef") + val newAppVersion = + AppVersion( + appVersionId = null, + appId = app.appId, + appVersion = appVersionInFolderDto.appVersion + ) + val savedAppVersionId = appVersionRepository.save(newAppVersion) + println("Saved new app version with ID: $savedAppVersionId") + newAppVersion.copy(appVersionId = savedAppVersionId) + } + } + + /** + * Retrieves an [ExecutionType] entity by its name. + * + * @param executionTypeName The name of the execution type. + * @return The [ExecutionType] entity. + * @throws IllegalArgumentException if the execution type is not found. + */ + private fun getExecutionType(executionTypeName: String): ExecutionType { + return executionTypeRepository.findByName(executionTypeName) + ?: throw IllegalArgumentException( + "Execution type not found: $executionTypeName" + ) + } - println("Creating new TestPlanVersion...") + /** + * Creates a new [TestPlanVersion] entity. + * + * @param request The [TestPlanVersionRequestDTO] containing version details. + * @param testPlanId The ID of the test plan. + * @param databaseDevice The [Device] entity. + * @param appVersionDef The [AppVersion] entity. + * @param executionType The [ExecutionType] entity. + * @return The newly created [TestPlanVersion] entity. + */ + private fun createTestPlanVersion( + request: TestPlanVersionRequestDTO, + testPlanId: Int, + databaseDevice: Device, + appVersionDef: AppVersion, + executionType: ExecutionType + ): TestPlanVersion { val newVersion = TestPlanVersion( testPlanVersionId = null, @@ -225,80 +364,135 @@ class TestPlanService( testPlanTestPlanId = testPlanId, deviceDeviceId = databaseDevice.deviceId!!, appVersionAppVersionId = appVersionDef.appVersionId!!, - executionTypeExecutionTypeId = request.executionTypeExecutionTypeId, + executionTypeExecutionTypeId = executionType.executionTypeId!!, appPackage = request.appPackage, mainActivity = request.mainActivity ) println("Saving new TestPlanVersion: $newVersion") val savedTestPlanVersionId = testPlanVersionRepository.save(newVersion) - val savedTestPlanVersion = - newVersion.copy(testPlanVersionId = savedTestPlanVersionId) println("Saved TestPlanVersion") + return newVersion.copy(testPlanVersionId = savedTestPlanVersionId) + } + /** + * Saves threshold entities for a test plan version. + * + * @param request The [TestPlanVersionRequestDTO] containing threshold details. + * @param savedTestPlanVersion The [TestPlanVersion] entity. + * @return List of saved [TestThreshold] entities. + * @throws IllegalArgumentException if a threshold type is not found. + */ + private fun saveThresholds( + request: TestPlanVersionRequestDTO, + savedTestPlanVersion: TestPlanVersion + ): List { println("Mapping thresholds...") val testThreshold = request.thresholds.map { threshold: TestThresholdRequestDTO -> - TestThreshold( - testThresholdId = null, - targetValue = threshold.targetValue, - thresholdTypeThresholdTypeId = - threshold.thresholdTypeThresholdTypeId, - testPlanVersionTestPlanVersionId = - savedTestPlanVersion.testPlanVersionId!!, - metricOutputMetricOutputId = - threshold.metricOutputMetricOutputId + val thresholdType = + thresholdTypeRepository.findByName(threshold.thresholdType) + ?: throw IllegalArgumentException( + "Threshold type not found: ${threshold.thresholdType}" + ) + TestThresholdMapper.fromRequestDto( + threshold, + savedTestPlanVersion.testPlanVersionId!!, + thresholdType.thresholdTypeId!! ) } println("Saving thresholds: $testThreshold") - val savedThresholds = - testThreshold.map { threshold -> - val id = testThresholdRepository.save(threshold) - threshold.copy(testThresholdId = id) - } - println("Saved all thresholds") + return testThreshold.map { threshold -> + val id = testThresholdRepository.save(threshold) + threshold.copy(testThresholdId = id) + } + } + /** + * Saves metric parameter entities for a test plan version. + * + * @param request The [TestPlanVersionRequestDTO] containing metric parameter details. + * @param savedTestPlanVersion The [TestPlanVersion] entity. + * @return List of saved [TestMetricParameter] entities. + */ + private fun saveMetricParameters( + request: TestPlanVersionRequestDTO, + savedTestPlanVersion: TestPlanVersion, + metric: Metric + ): List { println("Mapping metric parameters...") val testMetricParameters = request.metricParameters.map { parameter: TestMetricParameterRequestDTO -> - TestMetricParameter( - testMetricParameterId = null, - parameterValue = parameter.parameterValue, - metricParameterMetricParameterId = - parameter.metricParameterMetricParameterId, - testPlanVersionTestPlanVersionId = - savedTestPlanVersion.testPlanVersionId!! + val metricParameter = + metricParameterRepository.findByMetricIdAndName( + metric.metricId!!, + parameter.metricParameter + ) + ?: throw IllegalArgumentException( + "Metric parameter not found: ${parameter.metricParameter}" + ) + TestMetricParameterMapper.fromRequestDto( + parameter, + savedTestPlanVersion.testPlanVersionId!!, + metricParameter.metricParameterId!! ) } println("Saving metric parameters: $testMetricParameters") - val savedMetricParameters = - testMetricParameters.map { parameter -> - val id = testPlanMetricParameterRepository.save(parameter) - parameter.copy(testMetricParameterId = id) - } - println("Saved all metric parameters") + return testMetricParameters.map { parameter -> + val id = testPlanMetricParameterRepository.save(parameter) + parameter.copy(testMetricParameterId = id) + } + } + /** + * Saves execution type parameter entities for a test plan version. + * + * @param request The [TestPlanVersionRequestDTO] containing execution type parameter + * details. + * @param savedTestPlanVersion The [TestPlanVersion] entity. + * @return List of saved [TestExecutionTypeParameter] entities. + */ + private fun saveExecutionTypeParameters( + request: TestPlanVersionRequestDTO, + savedTestPlanVersion: TestPlanVersion + ): List { println("Mapping execution type parameters...") val testExecutionTypeParameters = request.executionTypeParameters.map { parameter: TestExecutionTypeParameterRequestDTO -> - TestExecutionTypeParameter( - testExecutionTypeParameterId = null, - parameterValue = parameter.parameterValue, - executionTypeParameterExecutionTypeParameterId = - parameter - .executionTypeParameterExecutionTypeParameterId, - testPlanVersionTestPlanVersionId = - savedTestPlanVersion.testPlanVersionId!! + val executionTypeParameter = + executionTypeParameterRepository + .findByExecutionTypeIdAndName( + savedTestPlanVersion + .executionTypeExecutionTypeId, + parameter.executionTypeParameter + ) + ?: throw IllegalArgumentException( + "Execution type parameter not found: ${parameter.executionTypeParameter}" + ) + TestExecutionTypeParameterMapper.fromRequestDto( + parameter, + savedTestPlanVersion.testPlanVersionId!!, + executionTypeParameter.executionTypeParameterId!! ) } println("Saving execution type parameters: $testExecutionTypeParameters") - val savedExecutionTypeParameters = - testExecutionTypeParameters.map { parameter -> - val id = testPlanExecutionTypeParameterRepository.save(parameter) - parameter.copy(testExecutionTypeParameterId = id) - } - println("Saved all execution type parameters") + return testExecutionTypeParameters.map { parameter -> + val id = testPlanExecutionTypeParameterRepository.save(parameter) + parameter.copy(testExecutionTypeParameterId = id) + } + } + /** + * Saves a [TestSuiteVersionPlan] entity associating a test suite version with a test plan + * version. + * + * @param request The [TestPlanVersionRequestDTO] containing suite version details. + * @param savedTestPlanVersion The [TestPlanVersion] entity. + */ + private fun saveTestSuiteVersionPlan( + request: TestPlanVersionRequestDTO, + savedTestPlanVersion: TestPlanVersion + ) { println( "Saving TestSuiteVersionPlan for testSuiteVersionId: ${request.testSuiteVersionId}" ) @@ -315,60 +509,5 @@ class TestPlanService( ) testSuiteVersionPlanRepository.save(testSuitePlanVersion) println("Saved TestSuiteVersionPlan") - - println("Returning TestPlanVersionResponseDTO") - return TestPlanVersionResponseDTO( - testPlanVersionId = savedTestPlanVersion.testPlanVersionId, - version = savedTestPlanVersion.version, - creationTimestamp = savedTestPlanVersion.creationTimestamp, - notes = savedTestPlanVersion.notes, - testPlanTestPlanId = savedTestPlanVersion.testPlanTestPlanId, - deviceDeviceId = databaseDevice.deviceId, - appVersionAppVersionId = savedTestPlanVersion.appVersionAppVersionId, - appPackage = savedTestPlanVersion.appPackage, - mainActivity = savedTestPlanVersion.mainActivity, - executionTypeExecutionTypeId = - savedTestPlanVersion.executionTypeExecutionTypeId, - thresholds = - savedThresholds.map { threshold: TestThreshold -> - TestThresholdResponseDTO( - testThresholdId = threshold.testThresholdId!!, - targetValue = threshold.targetValue, - thresholdTypeThresholdTypeId = - threshold.thresholdTypeThresholdTypeId, - testPlanVersionTestPlanVersionId = - threshold.testPlanVersionTestPlanVersionId, - metricOutputMetricOutputId = - threshold.metricOutputMetricOutputId - ) - }, - metricParameters = - savedMetricParameters.map { parameter: TestMetricParameter -> - TestMetricParameterResponseDTO( - testMetricParameterId = - parameter.testMetricParameterId!!, - parameterValue = parameter.parameterValue, - metricParameterMetricParameterId = - parameter.metricParameterMetricParameterId, - testPlanVersionTestPlanVersionId = - parameter.testPlanVersionTestPlanVersionId - ) - }, - executionTypeParameters = - savedExecutionTypeParameters.map { - parameter: TestExecutionTypeParameter -> - TestExecutionTypeParameterResponseDTO( - testExecutionTypeParameterId = - parameter.testExecutionTypeParameterId!!, - parameterValue = parameter.parameterValue, - executionTypeParameterExecutionTypeParameterId = - parameter - .executionTypeParameterExecutionTypeParameterId, - testPlanVersionTestPlanVersionId = - parameter.testPlanVersionTestPlanVersionId - ) - }, - testSuiteVersionId = request.testSuiteVersionId - ) } -} \ No newline at end of file +} diff --git a/Melmac/src/main/kotlin/services/TestPlanVersionService.kt b/Melmac/src/main/kotlin/services/TestPlanVersionService.kt index 4a4c3a5..9070e8f 100644 --- a/Melmac/src/main/kotlin/services/TestPlanVersionService.kt +++ b/Melmac/src/main/kotlin/services/TestPlanVersionService.kt @@ -4,6 +4,10 @@ import domain.* import dtos.* import repos.IRepos.* import services.IServices.ITestPlanVersionService +import mappers.TestThresholdMapper +import mappers.TestMetricParameterMapper +import mappers.TestExecutionTypeParameterMapper +import mappers.TestPlanVersionMapper /** * Service implementation for managing Test Plan Versions. @@ -37,74 +41,30 @@ class TestPlanVersionService( val versions = testPlanVersionRepository.findByTestPlanId(id) return versions.map { version: TestPlanVersion -> val thresholds = - testThresholdRepository.findByTestPlanVersionId(version.testPlanVersionId!!) - .map { threshold -> - TestThresholdResponseDTO( - testThresholdId = threshold.testThresholdId!!, - targetValue = threshold.targetValue, - thresholdTypeThresholdTypeId = - threshold.thresholdTypeThresholdTypeId, - testPlanVersionTestPlanVersionId = - threshold.testPlanVersionTestPlanVersionId, - metricOutputMetricOutputId = - threshold.metricOutputMetricOutputId - ) - } + testThresholdRepository.findByTestPlanVersionId(version.testPlanVersionId!!) + .map { threshold -> TestThresholdMapper.toDto(threshold) } val metricParameters = - testPlanMetricParameterRepository.findByTestPlanVersionId( - version.testPlanVersionId - ) - .map { parameter -> - TestMetricParameterResponseDTO( - testMetricParameterId = parameter.testMetricParameterId!!, - parameterValue = parameter.parameterValue, - metricParameterMetricParameterId = - parameter.metricParameterMetricParameterId, - testPlanVersionTestPlanVersionId = - parameter.testPlanVersionTestPlanVersionId - ) - } + testPlanMetricParameterRepository.findByTestPlanVersionId(version.testPlanVersionId) + .map { parameter -> TestMetricParameterMapper.toDto(parameter) } val executionTypeParameters = - testPlanExecutionTypeParameterRepository.findByTestPlanVersionId( - version.testPlanVersionId - ) - .map { parameter -> - TestExecutionTypeParameterResponseDTO( - testExecutionTypeParameterId = - parameter.testExecutionTypeParameterId!!, - parameterValue = parameter.parameterValue, - executionTypeParameterExecutionTypeParameterId = - parameter - .executionTypeParameterExecutionTypeParameterId, - testPlanVersionTestPlanVersionId = - parameter.testPlanVersionTestPlanVersionId - ) - } + testPlanExecutionTypeParameterRepository.findByTestPlanVersionId(version.testPlanVersionId) + .map { parameter -> TestExecutionTypeParameterMapper.toDto(parameter) } val testSuiteVersionId = - testSuiteVersionPlanRepository - .findByTestPlanVersionId(version.testPlanVersionId) - .firstOrNull() - ?.testSuiteVersionTestSuiteVersionId - ?: 0 - - TestPlanVersionResponseDTO( - testPlanVersionId = version.testPlanVersionId, - version = version.version, - creationTimestamp = version.creationTimestamp, - notes = version.notes, - testPlanTestPlanId = version.testPlanTestPlanId, - deviceDeviceId = version.deviceDeviceId, - appVersionAppVersionId = version.appVersionAppVersionId, - appPackage = version.appPackage, - mainActivity = version.mainActivity, - executionTypeExecutionTypeId = version.executionTypeExecutionTypeId, - thresholds = thresholds, - metricParameters = metricParameters, - executionTypeParameters = executionTypeParameters, - testSuiteVersionId = testSuiteVersionId + testSuiteVersionPlanRepository + .findByTestPlanVersionId(version.testPlanVersionId) + .firstOrNull() + ?.testSuiteVersionTestSuiteVersionId + ?: 0 + + TestPlanVersionMapper.toDto( + version, + thresholds, + metricParameters, + executionTypeParameters, + testSuiteVersionId ) } } @@ -120,73 +80,33 @@ class TestPlanVersionService( testPlanId: Int ): TestPlanVersionResponseDTO? { val version = - testPlanVersionRepository.findLatestVersionByTestPlanId(testPlanId) ?: return null + testPlanVersionRepository.findLatestVersionByTestPlanId(testPlanId) ?: return null val thresholds = - testThresholdRepository.findByTestPlanVersionId(version.testPlanVersionId!!).map { - threshold -> - TestThresholdResponseDTO( - testThresholdId = threshold.testThresholdId!!, - targetValue = threshold.targetValue, - thresholdTypeThresholdTypeId = threshold.thresholdTypeThresholdTypeId, - testPlanVersionTestPlanVersionId = - threshold.testPlanVersionTestPlanVersionId, - metricOutputMetricOutputId = threshold.metricOutputMetricOutputId - ) - } + testThresholdRepository.findByTestPlanVersionId(version.testPlanVersionId!!) + .map { threshold -> TestThresholdMapper.toDto(threshold) } val metricParameters = - testPlanMetricParameterRepository.findByTestPlanVersionId(version.testPlanVersionId) - .map { parameter -> - TestMetricParameterResponseDTO( - testMetricParameterId = parameter.testMetricParameterId!!, - parameterValue = parameter.parameterValue, - metricParameterMetricParameterId = - parameter.metricParameterMetricParameterId, - testPlanVersionTestPlanVersionId = - parameter.testPlanVersionTestPlanVersionId - ) - } + testPlanMetricParameterRepository.findByTestPlanVersionId(version.testPlanVersionId) + .map { parameter -> TestMetricParameterMapper.toDto(parameter) } val executionTypeParameters = - testPlanExecutionTypeParameterRepository.findByTestPlanVersionId( - version.testPlanVersionId - ) - .map { parameter -> - TestExecutionTypeParameterResponseDTO( - testExecutionTypeParameterId = - parameter.testExecutionTypeParameterId!!, - parameterValue = parameter.parameterValue, - executionTypeParameterExecutionTypeParameterId = - parameter - .executionTypeParameterExecutionTypeParameterId, - testPlanVersionTestPlanVersionId = - parameter.testPlanVersionTestPlanVersionId - ) - } + testPlanExecutionTypeParameterRepository.findByTestPlanVersionId(version.testPlanVersionId) + .map { parameter -> TestExecutionTypeParameterMapper.toDto(parameter) } val testSuiteVersionId = - testSuiteVersionPlanRepository - .findByTestPlanVersionId(version.testPlanVersionId) - .firstOrNull() - ?.testSuiteVersionTestSuiteVersionId - ?: 0 - - return TestPlanVersionResponseDTO( - testPlanVersionId = version.testPlanVersionId, - version = version.version, - creationTimestamp = version.creationTimestamp, - notes = version.notes, - testPlanTestPlanId = version.testPlanTestPlanId, - deviceDeviceId = version.deviceDeviceId, - appVersionAppVersionId = version.appVersionAppVersionId, - appPackage = version.appPackage, - mainActivity = version.mainActivity, - executionTypeExecutionTypeId = version.executionTypeExecutionTypeId, - thresholds = thresholds, - metricParameters = metricParameters, - executionTypeParameters = executionTypeParameters, - testSuiteVersionId = testSuiteVersionId + testSuiteVersionPlanRepository + .findByTestPlanVersionId(version.testPlanVersionId) + .firstOrNull() + ?.testSuiteVersionTestSuiteVersionId + ?: 0 + + return TestPlanVersionMapper.toDto( + version, + thresholds, + metricParameters, + executionTypeParameters, + testSuiteVersionId ) } @@ -201,70 +121,30 @@ class TestPlanVersionService( val version = testPlanVersionRepository.findById(id) ?: return null val thresholds = - testThresholdRepository.findByTestPlanVersionId(version.testPlanVersionId!!).map { - threshold -> - TestThresholdResponseDTO( - testThresholdId = threshold.testThresholdId!!, - targetValue = threshold.targetValue, - thresholdTypeThresholdTypeId = threshold.thresholdTypeThresholdTypeId, - testPlanVersionTestPlanVersionId = - threshold.testPlanVersionTestPlanVersionId, - metricOutputMetricOutputId = threshold.metricOutputMetricOutputId - ) - } + testThresholdRepository.findByTestPlanVersionId(version.testPlanVersionId!!) + .map { threshold -> TestThresholdMapper.toDto(threshold) } val metricParameters = - testPlanMetricParameterRepository.findByTestPlanVersionId(version.testPlanVersionId) - .map { parameter -> - TestMetricParameterResponseDTO( - testMetricParameterId = parameter.testMetricParameterId!!, - parameterValue = parameter.parameterValue, - metricParameterMetricParameterId = - parameter.metricParameterMetricParameterId, - testPlanVersionTestPlanVersionId = - parameter.testPlanVersionTestPlanVersionId - ) - } + testPlanMetricParameterRepository.findByTestPlanVersionId(version.testPlanVersionId) + .map { parameter -> TestMetricParameterMapper.toDto(parameter) } val executionTypeParameters = - testPlanExecutionTypeParameterRepository.findByTestPlanVersionId( - version.testPlanVersionId - ) - .map { parameter -> - TestExecutionTypeParameterResponseDTO( - testExecutionTypeParameterId = - parameter.testExecutionTypeParameterId!!, - parameterValue = parameter.parameterValue, - executionTypeParameterExecutionTypeParameterId = - parameter - .executionTypeParameterExecutionTypeParameterId, - testPlanVersionTestPlanVersionId = - parameter.testPlanVersionTestPlanVersionId - ) - } + testPlanExecutionTypeParameterRepository.findByTestPlanVersionId(version.testPlanVersionId) + .map { parameter -> TestExecutionTypeParameterMapper.toDto(parameter) } val testSuiteVersionId = - testSuiteVersionPlanRepository - .findByTestPlanVersionId(version.testPlanVersionId) - .firstOrNull() - ?.testSuiteVersionTestSuiteVersionId - ?: 0 - - return TestPlanVersionResponseDTO( - testPlanVersionId = version.testPlanVersionId, - version = version.version, - creationTimestamp = version.creationTimestamp, - notes = version.notes, - testPlanTestPlanId = version.testPlanTestPlanId, - deviceDeviceId = version.deviceDeviceId, - appVersionAppVersionId = version.appVersionAppVersionId, - appPackage = version.appPackage, - mainActivity = version.mainActivity, - executionTypeExecutionTypeId = version.executionTypeExecutionTypeId, - thresholds = thresholds, - metricParameters = metricParameters, - executionTypeParameters = executionTypeParameters, - testSuiteVersionId = testSuiteVersionId + testSuiteVersionPlanRepository + .findByTestPlanVersionId(version.testPlanVersionId) + .firstOrNull() + ?.testSuiteVersionTestSuiteVersionId + ?: 0 + + return TestPlanVersionMapper.toDto( + version, + thresholds, + metricParameters, + executionTypeParameters, + testSuiteVersionId ) } } \ No newline at end of file diff --git a/Melmac/src/main/kotlin/services/TestSuiteService.kt b/Melmac/src/main/kotlin/services/TestSuiteService.kt index 8ea559f..bd993aa 100644 --- a/Melmac/src/main/kotlin/services/TestSuiteService.kt +++ b/Melmac/src/main/kotlin/services/TestSuiteService.kt @@ -6,6 +6,10 @@ import repos.IRepos.* import services.IServices.ITestSuiteService import services.IServices.ITestExecutionService import java.time.LocalDateTime +import mappers.TestPlanVersionMapper +import mappers.TestThresholdMapper +import mappers.TestMetricParameterMapper +import mappers.TestExecutionTypeParameterMapper /** * Service implementation for managing Test Suites. @@ -41,10 +45,10 @@ class TestSuiteService( * @return List of [TestSuiteResponseDTO] representing all test suites. */ override fun getAllTestSuites(): List { - return testSuiteRepository.findAll().map {it -> + return testSuiteRepository.findAll().map { it -> TestSuiteResponseDTO( testSuiteId = it.testSuiteId!!, - testSuiteName = it.testSuiteName, + testSuiteName = it.testSuiteName, testSuiteDescription = it.testSuiteDescription, creationTimestamp = it.creationTimestamp, isActive = it.isActive @@ -112,59 +116,29 @@ class TestSuiteService( */ override fun getTestPlanVersionsBySuiteId(suiteId: Int): List { val latestVersion = testSuiteVersionRepository.findLatestVersionByTestSuiteId(suiteId) - if (latestVersion == null) { - throw IllegalArgumentException("TestSuite $suiteId has no versions") - } + ?: throw IllegalArgumentException("TestSuite $suiteId has no versions") val plans = testSuiteVersionPlanRepository.findByTestSuiteVersionId(latestVersion.testSuiteVersionId!!) return plans.mapNotNull { planLink: TestSuiteVersionPlan -> testPlanVersionRepository.findById(planLink.testPlanVersionTestPlanVersionId)?.let { planVersion: TestPlanVersion -> val thresholds = planVersion.testPlanVersionId?.let { id -> testThresholdRepository.findByTestPlanVersionId(id) + .map { TestThresholdMapper.toDto(it) } } ?: emptyList() val metricParameters = planVersion.testPlanVersionId?.let { id -> testMetricParameterRepository.findByTestPlanVersionId(id) + .map { TestMetricParameterMapper.toDto(it) } } ?: emptyList() val executionTypeParameters = planVersion.testPlanVersionId?.let { id -> testExecutionTypeParameterRepository.findByTestPlanVersionId(id) + .map { TestExecutionTypeParameterMapper.toDto(it) } } ?: emptyList() - TestPlanVersionResponseDTO( - testPlanVersionId = planVersion.testPlanVersionId!!, - version = planVersion.version, - creationTimestamp = planVersion.creationTimestamp, - notes = planVersion.notes, - testPlanTestPlanId = planVersion.testPlanTestPlanId, - deviceDeviceId = planVersion.deviceDeviceId, - appVersionAppVersionId = planVersion.appVersionAppVersionId, - appPackage = planVersion.appPackage, - mainActivity = planVersion.mainActivity, - executionTypeExecutionTypeId = planVersion.executionTypeExecutionTypeId, - thresholds = thresholds.map { threshold: TestThreshold -> - TestThresholdResponseDTO( - testThresholdId = threshold.testThresholdId ?: 0, - targetValue = threshold.targetValue, - thresholdTypeThresholdTypeId = threshold.thresholdTypeThresholdTypeId, - testPlanVersionTestPlanVersionId = threshold.testPlanVersionTestPlanVersionId, - metricOutputMetricOutputId = threshold.metricOutputMetricOutputId - ) - }, - metricParameters = metricParameters.map { parameter: TestMetricParameter -> - TestMetricParameterResponseDTO( - testMetricParameterId = parameter.testMetricParameterId ?: 0, - parameterValue = parameter.parameterValue, - metricParameterMetricParameterId = parameter.metricParameterMetricParameterId, - testPlanVersionTestPlanVersionId = parameter.testPlanVersionTestPlanVersionId - ) - }, - executionTypeParameters = executionTypeParameters.map { parameter: TestExecutionTypeParameter -> - TestExecutionTypeParameterResponseDTO( - testExecutionTypeParameterId = parameter.testExecutionTypeParameterId ?: 0, - parameterValue = parameter.parameterValue, - executionTypeParameterExecutionTypeParameterId = parameter.executionTypeParameterExecutionTypeParameterId, - testPlanVersionTestPlanVersionId = parameter.testPlanVersionTestPlanVersionId - ) - }, - testSuiteVersionId = latestVersion.testSuiteVersionId + TestPlanVersionMapper.toDto( + planVersion, + thresholds, + metricParameters, + executionTypeParameters, + latestVersion.testSuiteVersionId ) } } @@ -180,9 +154,7 @@ class TestSuiteService( */ override fun runTestSuiteExecution(suiteId: Int): SuiteExecutionResponseDTO { val latestVersion = testSuiteVersionRepository.findLatestVersionByTestSuiteId(suiteId) - if (latestVersion == null) { - throw IllegalArgumentException("TestSuite $suiteId has no versions") - } + ?: throw IllegalArgumentException("TestSuite $suiteId has no versions") val suitePlans = testSuiteVersionPlanRepository.findByTestSuiteVersionId(latestVersion.testSuiteVersionId!!) if (suitePlans.isEmpty()) { @@ -207,18 +179,10 @@ class TestSuiteService( return SuiteExecutionResponseDTO( suiteExecutionId = suiteExecutionId, - initialTimestamp = LocalDateTime.now(), - endTimestamp = LocalDateTime.now(), + initialTimestamp = startTime, + endTimestamp = endTime, testSuiteVersionTestSuiteVersionId = latestVersion.testSuiteVersionId, - executionResults = executionResults.map { result: TestExecutionResponseDTO -> - TestExecutionResponseDTO( - testExecutionId = result.testExecutionId, - initialTimestamp = LocalDateTime.now(), - endTimestamp = LocalDateTime.now(), - passed = if (result.passed == "true" || result.passed == "false") result.passed else "false", - testPlanVersionTestPlanVersionId = result.testPlanVersionTestPlanVersionId - ) - } + executionResults = executionResults ) } } \ No newline at end of file diff --git a/Melmac/src/main/kotlin/services/ThresholdService.kt b/Melmac/src/main/kotlin/services/ThresholdService.kt index 441fba3..9f81b82 100644 --- a/Melmac/src/main/kotlin/services/ThresholdService.kt +++ b/Melmac/src/main/kotlin/services/ThresholdService.kt @@ -3,7 +3,9 @@ package services import domain.* import dtos.* import repos.IRepos.IThresholdRepository +import repos.IRepos.IThresholdTypeRepository import services.IServices.IThresholdService +import mappers.TestThresholdMapper import java.time.LocalDateTime /** @@ -14,7 +16,8 @@ import java.time.LocalDateTime * @property thresholdRepository Repository for TestThreshold entities. */ class ThresholdService( - private val thresholdRepository: IThresholdRepository + private val thresholdRepository: IThresholdRepository, + private val thresholdTypeRepository: IThresholdTypeRepository ) : IThresholdService { /** @@ -26,13 +29,7 @@ class ThresholdService( override fun getThresholdByTestPlanVersionId(testPlanVersionId: Int): List { val thresholds = thresholdRepository.findByTestPlanVersionId(testPlanVersionId) return thresholds.map { threshold -> - TestThresholdResponseDTO( - testThresholdId = threshold.testThresholdId ?: 0, - thresholdTypeThresholdTypeId = threshold.thresholdTypeThresholdTypeId, - targetValue = threshold.targetValue, - metricOutputMetricOutputId = threshold.metricOutputMetricOutputId, - testPlanVersionTestPlanVersionId = threshold.testPlanVersionTestPlanVersionId - ) + TestThresholdMapper.toDto(threshold) } } @@ -44,13 +41,7 @@ class ThresholdService( */ override fun getThresholdById(id: Int): TestThresholdResponseDTO? { val threshold = thresholdRepository.findById(id) ?: return null - return TestThresholdResponseDTO( - testThresholdId = threshold.testThresholdId ?: 0, - thresholdTypeThresholdTypeId = threshold.thresholdTypeThresholdTypeId, - targetValue = threshold.targetValue, - metricOutputMetricOutputId = threshold.metricOutputMetricOutputId, - testPlanVersionTestPlanVersionId = threshold.testPlanVersionTestPlanVersionId - ) + return TestThresholdMapper.toDto(threshold) } /** @@ -60,21 +51,19 @@ class ThresholdService( * @return [TestThresholdResponseDTO] representing the created threshold. */ override fun createTestThreshold(request: TestThresholdRequestDTO): TestThresholdResponseDTO { - val newThreshold = TestThreshold( - testThresholdId = null, - targetValue = request.targetValue, - thresholdTypeThresholdTypeId = request.thresholdTypeThresholdTypeId, - testPlanVersionTestPlanVersionId = request.testPlanVersionTestPlanVersionId, - metricOutputMetricOutputId = request.metricOutputMetricOutputId + val thresholdTypeId = thresholdTypeRepository + .findByName(request.thresholdType) + ?.thresholdTypeId + ?: throw IllegalArgumentException("Threshold type not found: ${request.thresholdType}") + val newThreshold = TestThresholdMapper.fromRequestDto( + request, + request.testPlanVersionTestPlanVersionId, + thresholdTypeId ) val thresholdId = thresholdRepository.save(newThreshold) - return TestThresholdResponseDTO( - testThresholdId = thresholdId, - thresholdTypeThresholdTypeId = request.thresholdTypeThresholdTypeId, - targetValue = request.targetValue, - metricOutputMetricOutputId = request.metricOutputMetricOutputId, - testPlanVersionTestPlanVersionId = request.testPlanVersionTestPlanVersionId + return TestThresholdMapper.toDto( + newThreshold.copy(testThresholdId = thresholdId) ) } } \ No newline at end of file diff --git a/Melmac/src/main/kotlin/services/ThresholdTypeService.kt b/Melmac/src/main/kotlin/services/ThresholdTypeService.kt index f42cf1a..4e6c03c 100644 --- a/Melmac/src/main/kotlin/services/ThresholdTypeService.kt +++ b/Melmac/src/main/kotlin/services/ThresholdTypeService.kt @@ -3,6 +3,7 @@ package services import dtos.ThresholdTypeResponseDTO import repos.IRepos.IThresholdTypeRepository import services.IServices.IThresholdTypeService +import mappers.ThresholdTypeMapper /** * Service implementation for managing Threshold Types. @@ -21,11 +22,7 @@ class ThresholdTypeService(private val thresholdTypeRepository: IThresholdTypeRe */ override fun getAll(): List { return thresholdTypeRepository.findAll().map { - ThresholdTypeResponseDTO( - thresholdTypeId = it.thresholdTypeId ?: 0, - thresholdTypeName = it.thresholdTypeName, - thresholdTypeDescription = it.thresholdTypeDescription - ) + ThresholdTypeMapper.toDto(it) } } @@ -37,11 +34,7 @@ class ThresholdTypeService(private val thresholdTypeRepository: IThresholdTypeRe */ override fun getById(id: Int): ThresholdTypeResponseDTO? { return thresholdTypeRepository.findById(id)?.let { - ThresholdTypeResponseDTO( - thresholdTypeId = it.thresholdTypeId ?: 0, - thresholdTypeName = it.thresholdTypeName, - thresholdTypeDescription = it.thresholdTypeDescription - ) + ThresholdTypeMapper.toDto(it) } } @@ -53,11 +46,7 @@ class ThresholdTypeService(private val thresholdTypeRepository: IThresholdTypeRe */ override fun getByName(name: String): ThresholdTypeResponseDTO? { return thresholdTypeRepository.findByName(name)?.let { - ThresholdTypeResponseDTO( - thresholdTypeId = it.thresholdTypeId ?: 0, - thresholdTypeName = it.thresholdTypeName, - thresholdTypeDescription = it.thresholdTypeDescription - ) + ThresholdTypeMapper.toDto(it) } } } \ No newline at end of file diff --git a/Melmac/src/main/resources/MelmacDB.sql b/Melmac/src/main/resources/MelmacDB.sql index ad4b01b..f42c5aa 100644 --- a/Melmac/src/main/resources/MelmacDB.sql +++ b/Melmac/src/main/resources/MelmacDB.sql @@ -48,6 +48,7 @@ DROP TABLE TestSuiteVersion; DROP TABLE TestPlan; DROP TABLE TestPlanVersion; DROP TABLE TestSuiteVersionPlan; +DROP TABLE BootstrapUpdate; CREATE TABLE Device (DeviceID int IDENTITY NOT NULL, DeviceName varchar(255) NOT NULL, DeviceSerialNumber varchar(255) NULL, OSVersionOSVersionID int NOT NULL, PRIMARY KEY (DeviceID)); CREATE UNIQUE INDEX UQ_Device_Serial ON Device (DeviceSerialNumber) WHERE DeviceSerialNumber IS NOT NULL; CREATE TABLE OperativeSystem (OperSysID int IDENTITY NOT NULL, OperSysName varchar(255) NOT NULL UNIQUE, PRIMARY KEY (OperSysID)); CREATE TABLE OSVersion (OSVersionID int IDENTITY NOT NULL, Version varchar(255) NOT NULL, OperativeSystemOperSysID int NOT NULL, PRIMARY KEY (OSVersionID), CONSTRAINT UQ_VERSION_PER_OS UNIQUE (Version, OperativeSystemOperSysID)); @@ -71,6 +72,7 @@ CREATE TABLE TestSuiteVersion (TestSuiteVersionID int IDENTITY NOT NULL, Version CREATE TABLE TestPlan (TestPlanID int IDENTITY NOT NULL, TestName varchar(255) NOT NULL, MetricMetricID int NOT NULL, PRIMARY KEY (TestPlanID)); CREATE TABLE TestPlanVersion (TestPlanVersionID int IDENTITY NOT NULL, Version varchar(255) NOT NULL, CreationTimestamp datetime NOT NULL, Notes varchar(255) NULL, AppPackage varchar(255) NOT NULL, AppMainActivity varchar(255) NULL, TestPlanTestPlanID int NOT NULL, DeviceDeviceID int NOT NULL, AppVersionAppVersionID int NOT NULL, ExecutionTypeExecutionTypeID int NOT NULL, PRIMARY KEY (TestPlanVersionID), CONSTRAINT UQ_VERSION_PER_TEST_PLAN UNIQUE (Version, TestPlanTestPlanID)); CREATE TABLE TestSuiteVersionPlan (TestSuiteVersionTestSuiteVersionID int NOT NULL, TestPlanVersionTestPlanVersionID int NOT NULL, [Order] int NOT NULL, PRIMARY KEY (TestSuiteVersionTestSuiteVersionID, TestPlanVersionTestPlanVersionID), CONSTRAINT UQ_SUITE_VERSION_ORDER UNIQUE (TestSuiteVersionTestSuiteVersionID, [Order])); +CREATE TABLE BootstrapUpdate (BootstrapUpdateID int IDENTITY NOT NULL, UpdateDate datetime NOT NULL UNIQUE, PRIMARY KEY (BootstrapUpdateID)); ALTER TABLE OSVersion ADD CONSTRAINT FKOSVersion102342 FOREIGN KEY (OperativeSystemOperSysID) REFERENCES OperativeSystem (OperSysID); ALTER TABLE Device ADD CONSTRAINT FKDevice97329 FOREIGN KEY (OSVersionOSVersionID) REFERENCES OSVersion (OSVersionID); ALTER TABLE AppVersion ADD CONSTRAINT FKAppVersion811825 FOREIGN KEY (AppAppID) REFERENCES App (AppID); diff --git a/Melmac/src/main/resources/data.json b/Melmac/src/main/resources/data.json index 16e9fb6..a4c1331 100644 --- a/Melmac/src/main/resources/data.json +++ b/Melmac/src/main/resources/data.json @@ -1,4 +1,5 @@ { + "lastUpdated": "2025-06-03T09:34:00Z", "thresholdTypes": [ { "thresholdTypeName": "Min",