From 8bd7621958070958e6d5e25aa85f74697ef9dede Mon Sep 17 00:00:00 2001 From: ahmad Date: Mon, 28 Apr 2025 10:47:35 +0300 Subject: [PATCH 1/6] fix coverage report download --- .github/workflows/ci.yml | 45 +++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a1de4d3..7dc36a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,9 +14,8 @@ jobs: run-tests: name: Execute Tests & Generate Coverage runs-on: ubuntu-latest - steps: - - name: Checkout code + - name: Checkout uses: actions/checkout@v4 - name: Setup JDK 17 @@ -26,38 +25,60 @@ jobs: distribution: 'temurin' cache: gradle - - name: Make Gradle wrapper executable + - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Run tests & enforce coverage - run: ./gradlew clean check + - name: Run Unit Tests + run: ./gradlew test - - name: Generate XML coverage report + - name: Generate Kover XML Report run: ./gradlew koverXmlReport - - name: Upload coverage report artifact + - name: Upload coverage report XML uses: actions/upload-artifact@v4 if: always() with: name: kover-coverage-report - path: build/reports/kover/ + path: build/reports/kover/xml/report.xml retention-days: 1 + - name: Test Summary + uses: test-summary/action@v2 + with: + paths: "**/build/test-results/**/*.xml" + if: always() + + - name: Verify coverage thresholds + run: ./gradlew koverVerify + analyze-pr: - name: Comment Coverage Summary - runs-on: ubuntu-latest + name: Analyze PR Code Coverage needs: run-tests + runs-on: ubuntu-latest if: ${{ always() && github.event_name == 'pull_request' }} steps: - - name: Checkout code + - name: Checkout uses: actions/checkout@v4 + - name: Check for Kover artifact + id: check_artifact + uses: actions/github-script@v6 + with: + script: | + const artifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.runId + }); + return artifacts.data.artifacts.some(a => a.name === "kover-coverage-report"); + - name: Download coverage report + if: steps.check_artifact.outputs.result == 'true' uses: actions/download-artifact@v4 with: name: kover-coverage-report - path: build/reports/kover/ + path: build/reports/kover - name: Comment on PR with coverage uses: madrapps/jacoco-report@v1.7.1 From 6e029ea11b8f38e2c137ade24358315348a73832 Mon Sep 17 00:00:00 2001 From: Noha Saad Date: Thu, 1 May 2025 16:37:08 +0300 Subject: [PATCH 2/6] implement audit system logic and test cases --- .../logic/generateIdHelper/IdGenerator.kt | 11 ++ .../logic/generateIdHelper/generateId.kt | 13 +++ .../logic/repositories/AuditRepository.kt | 2 +- .../usecase/auditSystem/AddAuditLogUseCase.kt | 45 ++++++++ .../GetAuditLogsByProjectIdUseCase.kt | 22 ++++ .../GetAuditLogsByTaskIdUseCase.kt | 21 ++++ .../GetAuditLogsByUserIdUseCase.kt | 21 ++++ src/test/kotlin/helper/auditLogHelper.kt | 23 ++++ .../auditSystem/AddAuditLogUseCaseTest.kt | 102 ++++++++++++++++++ .../GetAuditLogsByProjectIdUseCaseTest.kt | 54 ++++++++++ .../GetAuditLogsByTaskIdUseCaseTest.kt | 54 ++++++++++ .../GetAuditLogsByUserIdUseCaseTest.kt | 67 ++++++++++++ 12 files changed, 434 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/logic/generateIdHelper/IdGenerator.kt create mode 100644 src/main/kotlin/logic/generateIdHelper/generateId.kt create mode 100644 src/main/kotlin/logic/usecase/auditSystem/AddAuditLogUseCase.kt create mode 100644 src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCase.kt create mode 100644 src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCase.kt create mode 100644 src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCase.kt create mode 100644 src/test/kotlin/helper/auditLogHelper.kt create mode 100644 src/test/kotlin/logic/usecase/auditSystem/AddAuditLogUseCaseTest.kt create mode 100644 src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCaseTest.kt create mode 100644 src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCaseTest.kt create mode 100644 src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCaseTest.kt diff --git a/src/main/kotlin/logic/generateIdHelper/IdGenerator.kt b/src/main/kotlin/logic/generateIdHelper/IdGenerator.kt new file mode 100644 index 0000000..14403de --- /dev/null +++ b/src/main/kotlin/logic/generateIdHelper/IdGenerator.kt @@ -0,0 +1,11 @@ +package com.berlin.logic.generateIdHelper + +import kotlin.random.Random + +interface IdGenerator { + fun generateId( + prefix: String, + padChar: Char = prefix[prefix.length / 2], + padCharLength: Int = prefix.length + Random.Default.nextInt(1, 5) + ): String +} \ No newline at end of file diff --git a/src/main/kotlin/logic/generateIdHelper/generateId.kt b/src/main/kotlin/logic/generateIdHelper/generateId.kt new file mode 100644 index 0000000..eccb920 --- /dev/null +++ b/src/main/kotlin/logic/generateIdHelper/generateId.kt @@ -0,0 +1,13 @@ +package com.berlin.logic.generateIdHelper + +class IdGeneratorImplementation : IdGenerator { + override fun generateId( + prefix: String, padChar: Char, padCharLength: Int): String { + val cleanedInput = prefix.trim().replace(" ", "") + .ifEmpty { throw IllegalArgumentException("String must not be empty") } + + val paddedNumber = cleanedInput.padEnd(padCharLength, padChar) + + return "${paddedNumber}_${System.currentTimeMillis() % 100000}" + } +} \ No newline at end of file diff --git a/src/main/kotlin/logic/repositories/AuditRepository.kt b/src/main/kotlin/logic/repositories/AuditRepository.kt index db0bcde..7311f16 100644 --- a/src/main/kotlin/logic/repositories/AuditRepository.kt +++ b/src/main/kotlin/logic/repositories/AuditRepository.kt @@ -3,7 +3,7 @@ package com.berlin.logic.repositories import com.berlin.model.AuditLog interface AuditRepository { - fun addAuditLog(auditLog: AuditLog):Boolean + fun addAuditLog(auditLog: AuditLog):Result fun getAuditLogsByProjectId(projectId:String):List fun getAuditLogsByTaskId(taskId:String):List fun getAuditLogsByUserId(userId:String):List diff --git a/src/main/kotlin/logic/usecase/auditSystem/AddAuditLogUseCase.kt b/src/main/kotlin/logic/usecase/auditSystem/AddAuditLogUseCase.kt new file mode 100644 index 0000000..354fa14 --- /dev/null +++ b/src/main/kotlin/logic/usecase/auditSystem/AddAuditLogUseCase.kt @@ -0,0 +1,45 @@ +package com.berlin.logic.usecase.auditSystem + +import com.berlin.logic.generateIdHelper.IdGenerator +import com.berlin.logic.repositories.AuditRepository +import com.berlin.model.AuditAction +import com.berlin.model.AuditLog +import com.berlin.model.EntityType +import com.berlin.model.User + +class AddAuditLogUseCase( + private val auditRepository: AuditRepository, + private val idGenerator: IdGenerator + +) { + + fun addAuditLog( + createdBy: User, + auditAction: AuditAction, + changesDescription: String, + entityType: EntityType, + entityId: String + ): Result { + return try { + val id = idGenerator.generateId("AUDIT") + val auditLog = AuditLog( + id = id, + timestamp = System.currentTimeMillis(), + createdBy = createdBy, + auditAction = auditAction, + changesDescription = changesDescription, + entityType = entityType, + entityId = entityId + ) + + val result = auditRepository.addAuditLog(auditLog) + if (result.isSuccess) { + result + } else { + Result.failure(Exception("Audit log failed to add")) + } + } catch (e: Exception) { + Result.failure(Exception("Audit log failed to add")) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCase.kt b/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCase.kt new file mode 100644 index 0000000..f50925b --- /dev/null +++ b/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCase.kt @@ -0,0 +1,22 @@ +package com.berlin.logic.usecase.auditSystem + +import com.berlin.logic.repositories.AuditRepository +import com.berlin.model.AuditLog + +class GetAuditLogsByProjectIdUseCase( + private val auditRepository: AuditRepository +) { + + fun getAuditLogsByProjectId(projectId: String): List { + + if (!validateProjectId(projectId)) + throw IllegalArgumentException("Project ID must not be empty, blank, or purely numeric") + + return auditRepository.getAuditLogsByProjectId(projectId) + + } + + private fun validateProjectId(projectId: String): Boolean = + projectId.isNotBlank() && !(projectId.all { it.isDigit() }) + +} \ No newline at end of file diff --git a/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCase.kt b/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCase.kt new file mode 100644 index 0000000..1da1623 --- /dev/null +++ b/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCase.kt @@ -0,0 +1,21 @@ +package com.berlin.logic.usecase.auditSystem + +import com.berlin.logic.repositories.AuditRepository +import com.berlin.model.AuditLog + +class GetAuditLogsByTaskIdUseCase( + private val auditRepository: AuditRepository +) { + + fun getAuditLogsByTaskId(taskId:String):List { + + if (!validateTaskId(taskId)) + throw IllegalArgumentException("Task ID must not be empty, blank, or purely numeric") + + return auditRepository.getAuditLogsByProjectId(taskId) + + } + + private fun validateTaskId(projectId: String): Boolean = + projectId.isNotBlank() && !(projectId.all { it.isDigit() }) + } \ No newline at end of file diff --git a/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCase.kt b/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCase.kt new file mode 100644 index 0000000..8cebfa2 --- /dev/null +++ b/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCase.kt @@ -0,0 +1,21 @@ +package com.berlin.logic.usecase.auditSystem + +import com.berlin.logic.repositories.AuditRepository +import com.berlin.model.AuditLog + +class GetAuditLogsByUserIdUseCase( + private val auditRepository: AuditRepository +) { + + fun getAuditLogsByUserId(userId:String):List{ + + if (!validateUserId(userId)) + throw IllegalArgumentException("User ID must not be empty, blank, or purely numeric") + + return auditRepository.getAuditLogsByUserId(userId) + + } + + private fun validateUserId(projectId: String): Boolean = + projectId.isNotBlank() && !(projectId.all { it.isDigit() }) +} diff --git a/src/test/kotlin/helper/auditLogHelper.kt b/src/test/kotlin/helper/auditLogHelper.kt new file mode 100644 index 0000000..1932a70 --- /dev/null +++ b/src/test/kotlin/helper/auditLogHelper.kt @@ -0,0 +1,23 @@ +package com.berlin.helper + +import com.berlin.model.* + +fun generateAuditLog( + id: String = "A1", + timestamp: Long = System.currentTimeMillis(), + createdBy: User = User("u1", "TestUser", "ffkjkuyu", UserRole.ADMIN), + action: AuditAction = AuditAction.CREATE, + changesDescription: String? = "Created something", + entityType: EntityType = EntityType.TASK, + entityId: String = "G2" +): AuditLog { + return AuditLog( + id = id, + timestamp = timestamp, + createdBy = createdBy, + auditAction = action, + changesDescription = changesDescription, + entityType = entityType, + entityId = entityId + ) +} diff --git a/src/test/kotlin/logic/usecase/auditSystem/AddAuditLogUseCaseTest.kt b/src/test/kotlin/logic/usecase/auditSystem/AddAuditLogUseCaseTest.kt new file mode 100644 index 0000000..faba2b1 --- /dev/null +++ b/src/test/kotlin/logic/usecase/auditSystem/AddAuditLogUseCaseTest.kt @@ -0,0 +1,102 @@ +package logic.usecase.auditSystem + +import com.berlin.helper.generateAuditLog +import com.berlin.logic.generateIdHelper.IdGenerator +import com.berlin.logic.repositories.AuditRepository +import com.berlin.logic.usecase.auditSystem.AddAuditLogUseCase +import com.berlin.model.AuditAction +import com.berlin.model.EntityType +import com.berlin.model.User +import com.berlin.model.UserRole +import com.google.common.truth.Truth.assertThat +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + + +class AddAuditLogUseCaseTest { + + private val auditRepository: AuditRepository = mockk(relaxed = true) + private val idGenerator: IdGenerator = mockk() + private lateinit var addAuditLogUseCase: AddAuditLogUseCase + + @BeforeEach + fun setup() { + addAuditLogUseCase = AddAuditLogUseCase(auditRepository, idGenerator) + + } + + @Test + fun `should return success when audit log is added successfully`() { + // Given + val generatedId = "AUDIT_12345" + val auditLog = generateAuditLog(id = generatedId) + every { idGenerator.generateId("AUDIT",any(),any()) } returns generatedId + every { auditRepository.addAuditLog(any()) } returns Result.success("Audit log added successfully") + + // When + val result = addAuditLogUseCase.addAuditLog( + createdBy = auditLog.createdBy, + auditAction = auditLog.auditAction, + changesDescription = auditLog.changesDescription!!, + entityType = auditLog.entityType, + entityId = auditLog.entityId + ) + + // Then + assertThat(result.isSuccess).isTrue() + assertThat(result.getOrNull()).isEqualTo("Audit log added successfully") + + verify(exactly = 1) { idGenerator.generateId("AUDIT",any(),any()) } + verify(exactly = 1) { auditRepository.addAuditLog(match { it.id == generatedId }) } + } + + @Test + fun `should return failure when audit log failed to add`() { + // Given + val generatedId = "AUDIT_12345" + val auditLog = generateAuditLog(id = generatedId) + every { idGenerator.generateId("AUDIT",any(),any()) } returns generatedId + every { auditRepository.addAuditLog(any()) } returns Result.failure(Exception("DB error")) + + // When + val result = addAuditLogUseCase.addAuditLog( + createdBy = auditLog.createdBy, + auditAction = auditLog.auditAction, + changesDescription = auditLog.changesDescription!!, + entityType = auditLog.entityType, + entityId = auditLog.entityId + ) + + // Then + assertThat(result.isFailure).isTrue() + assertThat(result.exceptionOrNull()?.message).isEqualTo("Audit log failed to add") + + verify(exactly = 1) { idGenerator.generateId("AUDIT",any(),any()) } + verify(exactly = 1) { auditRepository.addAuditLog(match { it.id == generatedId }) } + } + + @Test + fun `should return failure when id generator throws exception`() { + // Given + every { idGenerator.generateId("AUDIT",any(),any()) } throws IllegalArgumentException("Invalid prefix") + + // When + val result = addAuditLogUseCase.addAuditLog( + createdBy = User("u1", "TestUser", "ffkjkuyu", UserRole.ADMIN), + auditAction = AuditAction.CREATE, + changesDescription = "Created something", + entityType = EntityType.TASK, + entityId = "G2" + ) + + // Then + assertThat(result.isFailure).isTrue() + assertThat(result.exceptionOrNull()?.message).isEqualTo("Audit log failed to add") + + verify(exactly = 1) { idGenerator.generateId("AUDIT",any(),any()) } + verify(exactly = 0) { auditRepository.addAuditLog(any()) } + } +} \ No newline at end of file diff --git a/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCaseTest.kt b/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCaseTest.kt new file mode 100644 index 0000000..0ac4397 --- /dev/null +++ b/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCaseTest.kt @@ -0,0 +1,54 @@ +package logic.usecase.auditSystem + +import com.berlin.helper.generateAuditLog +import com.berlin.logic.repositories.AuditRepository +import com.berlin.logic.usecase.auditSystem.GetAuditLogsByProjectIdUseCase +import com.berlin.model.EntityType +import com.google.common.truth.Truth.assertThat +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource + +class GetAuditLogsByProjectIdUseCaseTest { + + private val auditRepository: AuditRepository = mockk(relaxed = true) + private lateinit var getAuditLogsByProjectIdUseCase: GetAuditLogsByProjectIdUseCase + + @BeforeEach + fun setup() { + getAuditLogsByProjectIdUseCase = GetAuditLogsByProjectIdUseCase(auditRepository) + } + + @Test + fun `should return list of logs for existing project ID`() { + // Given + val projectId = "D123" + val logs = listOf( + generateAuditLog(id = "A2", entityId = projectId, entityType = EntityType.PROJECT) + ) + every { auditRepository.getAuditLogsByProjectId(projectId) } returns logs + + //When + val result = getAuditLogsByProjectIdUseCase.getAuditLogsByProjectId(projectId) + + //That + assertThat(result).isEqualTo(logs) + verify(exactly = 1) { auditRepository.getAuditLogsByProjectId(projectId) } + + } + + @ParameterizedTest + @ValueSource(strings = ["", " ", "123"]) + fun `should throw exception when project Id is invalid`(invalidId: String) { + //when&then + assertThrows { + getAuditLogsByProjectIdUseCase.getAuditLogsByProjectId(invalidId) + } + } + +} \ No newline at end of file diff --git a/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCaseTest.kt b/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCaseTest.kt new file mode 100644 index 0000000..901a187 --- /dev/null +++ b/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCaseTest.kt @@ -0,0 +1,54 @@ +package logic.usecase.auditSystem + +import com.berlin.helper.generateAuditLog +import com.berlin.logic.repositories.AuditRepository +import com.berlin.logic.usecase.auditSystem.GetAuditLogsByTaskIdUseCase +import com.berlin.model.EntityType +import com.google.common.truth.Truth.assertThat +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource + +class GetAuditLogsByTaskIdUseCaseTest { + private val auditRepository: AuditRepository = mockk(relaxed = true) + private lateinit var getAuditLogsByTaskIdUseCase: GetAuditLogsByTaskIdUseCase + + @BeforeEach + fun setup() { + getAuditLogsByTaskIdUseCase = GetAuditLogsByTaskIdUseCase(auditRepository) + } + + @Test + fun `should return list of logs for existing task ID`() { + // Given + val taskId = "T123" + val logs = listOf( + generateAuditLog(id = "A3", entityId = taskId, entityType = EntityType.TASK) + ) + every { auditRepository.getAuditLogsByProjectId(taskId) } returns logs + + //When + val result = getAuditLogsByTaskIdUseCase.getAuditLogsByTaskId(taskId) + + //That + assertThat(result).isEqualTo(logs) + verify(exactly = 1) { auditRepository.getAuditLogsByProjectId(taskId) } + + } + + + @ParameterizedTest + @ValueSource(strings = ["", " ","123"]) + fun `should throw Exception when task id is invalid`(invalidId: String) { + //when&then + assertThrows { + getAuditLogsByTaskIdUseCase.getAuditLogsByTaskId(invalidId) + } + } + +} \ No newline at end of file diff --git a/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCaseTest.kt b/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCaseTest.kt new file mode 100644 index 0000000..7750043 --- /dev/null +++ b/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCaseTest.kt @@ -0,0 +1,67 @@ +package logic.usecase.auditSystem + +import com.berlin.helper.generateAuditLog +import com.berlin.logic.repositories.AuditRepository +import com.berlin.logic.usecase.auditSystem.GetAuditLogsByUserIdUseCase +import com.google.common.truth.Truth.assertThat +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource + +class GetAuditLogsByUserIdUseCaseTest { + private val auditRepository: AuditRepository = mockk(relaxed = true) + private lateinit var getAuditLogsByUserIdUseCase: GetAuditLogsByUserIdUseCase + + @BeforeEach + fun setup() { + getAuditLogsByUserIdUseCase = GetAuditLogsByUserIdUseCase(auditRepository) + } + + @Test + fun `should return list of logs for user ID`() { + // Given + val userId = "u1" + val logs = listOf( + generateAuditLog(createdBy = generateAuditLog().createdBy) + ) + every { auditRepository.getAuditLogsByUserId(userId) } returns logs + + //When + val result = getAuditLogsByUserIdUseCase.getAuditLogsByUserId(userId) + + //That + assertThat(result).isEqualTo(logs) + verify(exactly = 1) { auditRepository.getAuditLogsByUserId(userId) } + + } + + @Test + fun `should return empty list when no audit logs found for user ID`() { + // Given + val userId = "invalid" + every { auditRepository.getAuditLogsByUserId(userId) } returns emptyList() + + //When + val result = getAuditLogsByUserIdUseCase.getAuditLogsByUserId(userId) + + //That + assertThat(result).isEmpty() + verify(exactly = 1) { auditRepository.getAuditLogsByUserId(userId) } + } + + @ParameterizedTest + @ValueSource(strings = ["", " ","123"]) + fun `should throw exception when user id is invalid`(invalidId: String) { + //when&then + assertThrows { + getAuditLogsByUserIdUseCase.getAuditLogsByUserId(invalidId) + } + } + + +} \ No newline at end of file From 956e3c314e07aa9bb092cf083d0f997611196b9d Mon Sep 17 00:00:00 2001 From: Noha Saad Date: Fri, 2 May 2025 16:15:17 +0300 Subject: [PATCH 3/6] refactor audit system structure and remove unused helpers --- .../repository}/AuditRepository.kt | 4 +- .../usecase/auditSystem/AddAuditLogUseCase.kt | 26 ++++++------ .../GetAuditLogsByProjectIdUseCase.kt | 6 +-- .../GetAuditLogsByTaskIdUseCase.kt | 6 +-- .../GetAuditLogsByUserIdUseCase.kt | 6 +-- .../logic/generateIdHelper/IdGenerator.kt | 11 ----- .../IdGeneratorImplementation.kt | 13 ------ .../logic/generateIdHelper/generateId.kt | 13 ------ .../logic/repositories/ProjectRepository.kt | 11 ----- .../logic/repositories/StateRepository.kt | 14 ------- .../logic/repositories/TaskRepository.kt | 13 ------ .../usecase/project/CreateProjectUseCase.kt | 31 -------------- .../usecase/project/DeleteProjectUseCase.kt | 29 -------------- .../usecase/project/GetAllProjectsUseCase.kt | 13 ------ .../usecase/project/GetProjectByIdUseCase.kt | 21 ---------- .../usecase/project/UpdateProjectUseCase.kt | 21 ---------- src/main/kotlin/model/Project.kt | 9 ----- src/main/kotlin/model/Task.kt | 12 ------ src/main/kotlin/model/User.kt | 10 ----- .../auditSystem/AddAuditLogUseCaseTest.kt | 40 +++++++++---------- .../GetAuditLogsByProjectIdUseCaseTest.kt | 7 ++-- .../GetAuditLogsByTaskIdUseCaseTest.kt | 7 ++-- .../GetAuditLogsByUserIdUseCaseTest.kt | 7 ++-- src/test/kotlin/helper/auditLogHelper.kt | 8 +++- 24 files changed, 57 insertions(+), 281 deletions(-) rename src/main/kotlin/{logic/repositories => domain/repository}/AuditRepository.kt (77%) rename src/main/kotlin/{logic => domain}/usecase/auditSystem/AddAuditLogUseCase.kt (61%) rename src/main/kotlin/{logic => domain}/usecase/auditSystem/GetAuditLogsByProjectIdUseCase.kt (78%) rename src/main/kotlin/{logic => domain}/usecase/auditSystem/GetAuditLogsByTaskIdUseCase.kt (78%) rename src/main/kotlin/{logic => domain}/usecase/auditSystem/GetAuditLogsByUserIdUseCase.kt (77%) delete mode 100644 src/main/kotlin/logic/generateIdHelper/IdGenerator.kt delete mode 100644 src/main/kotlin/logic/generateIdHelper/IdGeneratorImplementation.kt delete mode 100644 src/main/kotlin/logic/generateIdHelper/generateId.kt delete mode 100644 src/main/kotlin/logic/repositories/ProjectRepository.kt delete mode 100644 src/main/kotlin/logic/repositories/StateRepository.kt delete mode 100644 src/main/kotlin/logic/repositories/TaskRepository.kt delete mode 100644 src/main/kotlin/logic/usecase/project/CreateProjectUseCase.kt delete mode 100644 src/main/kotlin/logic/usecase/project/DeleteProjectUseCase.kt delete mode 100644 src/main/kotlin/logic/usecase/project/GetAllProjectsUseCase.kt delete mode 100644 src/main/kotlin/logic/usecase/project/GetProjectByIdUseCase.kt delete mode 100644 src/main/kotlin/logic/usecase/project/UpdateProjectUseCase.kt delete mode 100644 src/main/kotlin/model/Project.kt delete mode 100644 src/main/kotlin/model/Task.kt delete mode 100644 src/main/kotlin/model/User.kt rename src/test/kotlin/{logic => domain}/usecase/auditSystem/AddAuditLogUseCaseTest.kt (70%) rename src/test/kotlin/{logic => domain}/usecase/auditSystem/GetAuditLogsByProjectIdUseCaseTest.kt (89%) rename src/test/kotlin/{logic => domain}/usecase/auditSystem/GetAuditLogsByTaskIdUseCaseTest.kt (88%) rename src/test/kotlin/{logic => domain}/usecase/auditSystem/GetAuditLogsByUserIdUseCaseTest.kt (92%) diff --git a/src/main/kotlin/logic/repositories/AuditRepository.kt b/src/main/kotlin/domain/repository/AuditRepository.kt similarity index 77% rename from src/main/kotlin/logic/repositories/AuditRepository.kt rename to src/main/kotlin/domain/repository/AuditRepository.kt index 7311f16..94856bb 100644 --- a/src/main/kotlin/logic/repositories/AuditRepository.kt +++ b/src/main/kotlin/domain/repository/AuditRepository.kt @@ -1,6 +1,6 @@ -package com.berlin.logic.repositories +package com.berlin.domain.repository -import com.berlin.model.AuditLog +import com.berlin.domain.model.AuditLog interface AuditRepository { fun addAuditLog(auditLog: AuditLog):Result diff --git a/src/main/kotlin/logic/usecase/auditSystem/AddAuditLogUseCase.kt b/src/main/kotlin/domain/usecase/auditSystem/AddAuditLogUseCase.kt similarity index 61% rename from src/main/kotlin/logic/usecase/auditSystem/AddAuditLogUseCase.kt rename to src/main/kotlin/domain/usecase/auditSystem/AddAuditLogUseCase.kt index 354fa14..f43a0c4 100644 --- a/src/main/kotlin/logic/usecase/auditSystem/AddAuditLogUseCase.kt +++ b/src/main/kotlin/domain/usecase/auditSystem/AddAuditLogUseCase.kt @@ -1,31 +1,31 @@ -package com.berlin.logic.usecase.auditSystem +package com.berlin.domain.usecase.auditSystem -import com.berlin.logic.generateIdHelper.IdGenerator -import com.berlin.logic.repositories.AuditRepository -import com.berlin.model.AuditAction -import com.berlin.model.AuditLog -import com.berlin.model.EntityType -import com.berlin.model.User +import com.berlin.domain.helper.IdGenerator +import com.berlin.domain.model.AuditAction +import com.berlin.domain.model.AuditLog +import com.berlin.domain.model.EntityType +import com.berlin.domain.repository.AuditRepository +import com.berlin.domain.model.User class AddAuditLogUseCase( private val auditRepository: AuditRepository, private val idGenerator: IdGenerator - ) { fun addAuditLog( - createdBy: User, + createdByUserId:User, auditAction: AuditAction, changesDescription: String, entityType: EntityType, - entityId: String + entityId: String, + timestamp: Long = System.currentTimeMillis() ): Result { return try { val id = idGenerator.generateId("AUDIT") val auditLog = AuditLog( id = id, - timestamp = System.currentTimeMillis(), - createdBy = createdBy, + timestamp = timestamp, + createdByUserId=createdByUserId, auditAction = auditAction, changesDescription = changesDescription, entityType = entityType, @@ -34,7 +34,7 @@ class AddAuditLogUseCase( val result = auditRepository.addAuditLog(auditLog) if (result.isSuccess) { - result + Result.success("Audit log added successfully") } else { Result.failure(Exception("Audit log failed to add")) } diff --git a/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCase.kt b/src/main/kotlin/domain/usecase/auditSystem/GetAuditLogsByProjectIdUseCase.kt similarity index 78% rename from src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCase.kt rename to src/main/kotlin/domain/usecase/auditSystem/GetAuditLogsByProjectIdUseCase.kt index f50925b..bafb40e 100644 --- a/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCase.kt +++ b/src/main/kotlin/domain/usecase/auditSystem/GetAuditLogsByProjectIdUseCase.kt @@ -1,7 +1,7 @@ -package com.berlin.logic.usecase.auditSystem +package com.berlin.domain.usecase.auditSystem -import com.berlin.logic.repositories.AuditRepository -import com.berlin.model.AuditLog +import com.berlin.domain.model.AuditLog +import com.berlin.domain.repository.AuditRepository class GetAuditLogsByProjectIdUseCase( private val auditRepository: AuditRepository diff --git a/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCase.kt b/src/main/kotlin/domain/usecase/auditSystem/GetAuditLogsByTaskIdUseCase.kt similarity index 78% rename from src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCase.kt rename to src/main/kotlin/domain/usecase/auditSystem/GetAuditLogsByTaskIdUseCase.kt index 1da1623..d819a41 100644 --- a/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCase.kt +++ b/src/main/kotlin/domain/usecase/auditSystem/GetAuditLogsByTaskIdUseCase.kt @@ -1,7 +1,7 @@ -package com.berlin.logic.usecase.auditSystem +package com.berlin.domain.usecase.auditSystem -import com.berlin.logic.repositories.AuditRepository -import com.berlin.model.AuditLog +import com.berlin.domain.model.AuditLog +import com.berlin.domain.repository.AuditRepository class GetAuditLogsByTaskIdUseCase( private val auditRepository: AuditRepository diff --git a/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCase.kt b/src/main/kotlin/domain/usecase/auditSystem/GetAuditLogsByUserIdUseCase.kt similarity index 77% rename from src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCase.kt rename to src/main/kotlin/domain/usecase/auditSystem/GetAuditLogsByUserIdUseCase.kt index 8cebfa2..0f7af63 100644 --- a/src/main/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCase.kt +++ b/src/main/kotlin/domain/usecase/auditSystem/GetAuditLogsByUserIdUseCase.kt @@ -1,7 +1,7 @@ -package com.berlin.logic.usecase.auditSystem +package com.berlin.domain.usecase.auditSystem -import com.berlin.logic.repositories.AuditRepository -import com.berlin.model.AuditLog +import com.berlin.domain.model.AuditLog +import com.berlin.domain.repository.AuditRepository class GetAuditLogsByUserIdUseCase( private val auditRepository: AuditRepository diff --git a/src/main/kotlin/logic/generateIdHelper/IdGenerator.kt b/src/main/kotlin/logic/generateIdHelper/IdGenerator.kt deleted file mode 100644 index ef5b3d5..0000000 --- a/src/main/kotlin/logic/generateIdHelper/IdGenerator.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.berlin.logic.generateIdHelper - -import kotlin.random.Random - -interface IdGenerator { - fun generateId( - prefix: String, - padChar: Char = prefix[prefix.length / 2], - padCharLength: Int = prefix.length + Random.nextInt(1, 5) - ): String -} \ No newline at end of file diff --git a/src/main/kotlin/logic/generateIdHelper/IdGeneratorImplementation.kt b/src/main/kotlin/logic/generateIdHelper/IdGeneratorImplementation.kt deleted file mode 100644 index eccb920..0000000 --- a/src/main/kotlin/logic/generateIdHelper/IdGeneratorImplementation.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.berlin.logic.generateIdHelper - -class IdGeneratorImplementation : IdGenerator { - override fun generateId( - prefix: String, padChar: Char, padCharLength: Int): String { - val cleanedInput = prefix.trim().replace(" ", "") - .ifEmpty { throw IllegalArgumentException("String must not be empty") } - - val paddedNumber = cleanedInput.padEnd(padCharLength, padChar) - - return "${paddedNumber}_${System.currentTimeMillis() % 100000}" - } -} \ No newline at end of file diff --git a/src/main/kotlin/logic/generateIdHelper/generateId.kt b/src/main/kotlin/logic/generateIdHelper/generateId.kt deleted file mode 100644 index eccb920..0000000 --- a/src/main/kotlin/logic/generateIdHelper/generateId.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.berlin.logic.generateIdHelper - -class IdGeneratorImplementation : IdGenerator { - override fun generateId( - prefix: String, padChar: Char, padCharLength: Int): String { - val cleanedInput = prefix.trim().replace(" ", "") - .ifEmpty { throw IllegalArgumentException("String must not be empty") } - - val paddedNumber = cleanedInput.padEnd(padCharLength, padChar) - - return "${paddedNumber}_${System.currentTimeMillis() % 100000}" - } -} \ No newline at end of file diff --git a/src/main/kotlin/logic/repositories/ProjectRepository.kt b/src/main/kotlin/logic/repositories/ProjectRepository.kt deleted file mode 100644 index 07519a5..0000000 --- a/src/main/kotlin/logic/repositories/ProjectRepository.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.berlin.logic.repositories - -import com.berlin.model.Project - -interface ProjectRepository { - fun createProject(project:Project): Result - fun getProjectById(projectId:String): Project? - fun getAllProjects(): List? - fun updateProject(project: Project): Result - fun deleteProject(projectId: String): Result -} \ No newline at end of file diff --git a/src/main/kotlin/logic/repositories/StateRepository.kt b/src/main/kotlin/logic/repositories/StateRepository.kt deleted file mode 100644 index 2842b9f..0000000 --- a/src/main/kotlin/logic/repositories/StateRepository.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.berlin.logic.repositories - -import com.berlin.domain.model.State -import com.berlin.model.Task - -interface StateRepository { - fun addState(state: State): Result - fun getStatesByProjectId(projectId: String):List? - fun getTasksByStateId(stateId: String):List? - fun deleteState(stateId: String): Result - fun updateState(state: State): Result - fun getStateByTaskId(taskId: String): State? - fun getStateById(stateId: String): State? -} \ No newline at end of file diff --git a/src/main/kotlin/logic/repositories/TaskRepository.kt b/src/main/kotlin/logic/repositories/TaskRepository.kt deleted file mode 100644 index 5dbbae8..0000000 --- a/src/main/kotlin/logic/repositories/TaskRepository.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.berlin.logic.repositories - -import com.berlin.model.Task -import com.berlin.model.User - -interface TaskRepository { - fun createTask(task:Task):Boolean - fun getTaskById(taskId:String):Task? - fun getTasksByProjectId(projectId:String):List - fun updateTask(task: Task):Boolean - fun deleteTaskById(taskId: String):Boolean - fun getAssignedUserByTaskId(taskId: String):User? -} \ No newline at end of file diff --git a/src/main/kotlin/logic/usecase/project/CreateProjectUseCase.kt b/src/main/kotlin/logic/usecase/project/CreateProjectUseCase.kt deleted file mode 100644 index 673ce40..0000000 --- a/src/main/kotlin/logic/usecase/project/CreateProjectUseCase.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.berlin.logic.usecase.project - -import com.berlin.logic.generateIdHelper.IdGenerator -import com.berlin.logic.repositories.ProjectRepository -import com.berlin.model.Project - -class CreateProjectUseCase( - private val projectRepository: ProjectRepository, - private val idGenerator: IdGenerator, - ) { - fun createNewProject(projectName: String, description: String?, stateId: List?, taskId: List?): - Result { - if (validateProjectName(projectName)) { - val newProject = Project( - id = idGenerator.generateId(projectName), - name = projectName, - description = description, - statesId = stateId, - tasksId = taskId - ) - return projectRepository.createProject(newProject) - .map { "Creation Successfully" } - .recover { "Creation Failed" } - } else { - throw Exception("Project Name must not be empty or blank") - } - } - - private fun validateProjectName(projectName: String): Boolean = - projectName.isNotBlank() && !(projectName.all { it.isDigit() }) -} \ No newline at end of file diff --git a/src/main/kotlin/logic/usecase/project/DeleteProjectUseCase.kt b/src/main/kotlin/logic/usecase/project/DeleteProjectUseCase.kt deleted file mode 100644 index ca87e77..0000000 --- a/src/main/kotlin/logic/usecase/project/DeleteProjectUseCase.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.berlin.logic.usecase.project - -import com.berlin.logic.repositories.ProjectRepository - -class DeleteProjectUseCase ( - private val projectRepository: ProjectRepository -) { - fun deleteProject(projectId: String): Result { - - if(!validateProjectId(projectId)) - throw Exception("Project ID must not be empty or blank") - - if (!checkProjectExists(projectId)) { - return Result.failure( - Exception("Project with ID $projectId does not exist") - ) - } - - return projectRepository.deleteProject(projectId) - .map { "Deleted Successfully" } - .recover { "Deletion Failed" } - } - - private fun validateProjectId(projectId: String): Boolean = - projectId.isNotBlank() && !(projectId.all { it.isDigit() }) - - private fun checkProjectExists(projectId: String): Boolean = - projectRepository.getProjectById(projectId) != null -} \ No newline at end of file diff --git a/src/main/kotlin/logic/usecase/project/GetAllProjectsUseCase.kt b/src/main/kotlin/logic/usecase/project/GetAllProjectsUseCase.kt deleted file mode 100644 index 736b3f4..0000000 --- a/src/main/kotlin/logic/usecase/project/GetAllProjectsUseCase.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.berlin.logic.usecase.project - -import com.berlin.logic.repositories.ProjectRepository -import com.berlin.model.Project - -class GetAllProjectsUseCase( - private val projectRepository: ProjectRepository -) { - fun getAllProjects(): List { - return projectRepository.getAllProjects() - ?: throw Exception("No projects found") - } -} \ No newline at end of file diff --git a/src/main/kotlin/logic/usecase/project/GetProjectByIdUseCase.kt b/src/main/kotlin/logic/usecase/project/GetProjectByIdUseCase.kt deleted file mode 100644 index b4774d8..0000000 --- a/src/main/kotlin/logic/usecase/project/GetProjectByIdUseCase.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.berlin.logic.usecase.project - -import com.berlin.logic.repositories.ProjectRepository -import com.berlin.model.Project - -class GetProjectByIdUseCase ( - private val projectRepository: ProjectRepository -) { - - fun getProjectById(projectId: String): Project { - if(!validateProjectId(projectId)) - throw Exception("Project ID must not be empty or blank") - - return projectRepository.getProjectById(projectId) - ?: throw Exception("Project with ID $projectId does not exist") - } - - private fun validateProjectId(projectId: String): Boolean = - projectId.isNotBlank() && !(projectId.all { it.isDigit() }) - -} \ No newline at end of file diff --git a/src/main/kotlin/logic/usecase/project/UpdateProjectUseCase.kt b/src/main/kotlin/logic/usecase/project/UpdateProjectUseCase.kt deleted file mode 100644 index de4037f..0000000 --- a/src/main/kotlin/logic/usecase/project/UpdateProjectUseCase.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.berlin.logic.usecase.project - -import com.berlin.logic.repositories.ProjectRepository -import com.berlin.model.Project - -class UpdateProjectUseCase ( - private val projectRepository: ProjectRepository -) { - fun updateProject(project: Project): Result { - if(!validateProjectName(project.name)) - throw Exception("Project Name must not be empty or blank") - - return projectRepository.updateProject(project) - .map { "Updated Successfully" } - .recover { "Update Failed" } - } - - - private fun validateProjectName(projectName: String): Boolean = - projectName.isNotBlank() && !(projectName.all { it.isDigit() }) -} \ No newline at end of file diff --git a/src/main/kotlin/model/Project.kt b/src/main/kotlin/model/Project.kt deleted file mode 100644 index e459a0c..0000000 --- a/src/main/kotlin/model/Project.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.berlin.model - -data class Project( - val id:String, - val name:String, - val description:String?, - val statesId:List?, - val tasksId:List? -) diff --git a/src/main/kotlin/model/Task.kt b/src/main/kotlin/model/Task.kt deleted file mode 100644 index 22d385c..0000000 --- a/src/main/kotlin/model/Task.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.berlin.model - - -data class Task( - val id:String, - val projectId:String, - val title:String, - val description:String?, - val stateId:String, - val assignedTo: String, - val createBy: String -) diff --git a/src/main/kotlin/model/User.kt b/src/main/kotlin/model/User.kt deleted file mode 100644 index 162a319..0000000 --- a/src/main/kotlin/model/User.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.berlin.model - -import com.berlin.domain.model.UserRole - -data class User( - val id:String, - val userName:String, - val password:String, - val role: UserRole -) \ No newline at end of file diff --git a/src/test/kotlin/logic/usecase/auditSystem/AddAuditLogUseCaseTest.kt b/src/test/kotlin/domain/usecase/auditSystem/AddAuditLogUseCaseTest.kt similarity index 70% rename from src/test/kotlin/logic/usecase/auditSystem/AddAuditLogUseCaseTest.kt rename to src/test/kotlin/domain/usecase/auditSystem/AddAuditLogUseCaseTest.kt index faba2b1..e3eee95 100644 --- a/src/test/kotlin/logic/usecase/auditSystem/AddAuditLogUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/auditSystem/AddAuditLogUseCaseTest.kt @@ -1,23 +1,16 @@ -package logic.usecase.auditSystem +package com.berlin.domain.usecase.auditSystem +import com.berlin.domain.helper.IdGenerator +import com.berlin.domain.model.* +import com.berlin.domain.repository.AuditRepository import com.berlin.helper.generateAuditLog -import com.berlin.logic.generateIdHelper.IdGenerator -import com.berlin.logic.repositories.AuditRepository -import com.berlin.logic.usecase.auditSystem.AddAuditLogUseCase -import com.berlin.model.AuditAction -import com.berlin.model.EntityType -import com.berlin.model.User -import com.berlin.model.UserRole import com.google.common.truth.Truth.assertThat -import io.mockk.every -import io.mockk.mockk -import io.mockk.verify +import io.mockk.* import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test class AddAuditLogUseCaseTest { - private val auditRepository: AuditRepository = mockk(relaxed = true) private val idGenerator: IdGenerator = mockk() private lateinit var addAuditLogUseCase: AddAuditLogUseCase @@ -33,12 +26,12 @@ class AddAuditLogUseCaseTest { // Given val generatedId = "AUDIT_12345" val auditLog = generateAuditLog(id = generatedId) - every { idGenerator.generateId("AUDIT",any(),any()) } returns generatedId + every { idGenerator.generateId("AUDIT", any(), any()) } returns generatedId every { auditRepository.addAuditLog(any()) } returns Result.success("Audit log added successfully") // When val result = addAuditLogUseCase.addAuditLog( - createdBy = auditLog.createdBy, + createdByUserId = auditLog.createdByUserId, auditAction = auditLog.auditAction, changesDescription = auditLog.changesDescription!!, entityType = auditLog.entityType, @@ -49,7 +42,7 @@ class AddAuditLogUseCaseTest { assertThat(result.isSuccess).isTrue() assertThat(result.getOrNull()).isEqualTo("Audit log added successfully") - verify(exactly = 1) { idGenerator.generateId("AUDIT",any(),any()) } + verify(exactly = 1) { idGenerator.generateId("AUDIT", any(), any()) } verify(exactly = 1) { auditRepository.addAuditLog(match { it.id == generatedId }) } } @@ -58,12 +51,12 @@ class AddAuditLogUseCaseTest { // Given val generatedId = "AUDIT_12345" val auditLog = generateAuditLog(id = generatedId) - every { idGenerator.generateId("AUDIT",any(),any()) } returns generatedId - every { auditRepository.addAuditLog(any()) } returns Result.failure(Exception("DB error")) + every { idGenerator.generateId("AUDIT", any(), any()) } returns generatedId + every { auditRepository.addAuditLog(any()) } returns Result.failure(Exception("audit log failed to add")) // When val result = addAuditLogUseCase.addAuditLog( - createdBy = auditLog.createdBy, + createdByUserId = auditLog.createdByUserId, auditAction = auditLog.auditAction, changesDescription = auditLog.changesDescription!!, entityType = auditLog.entityType, @@ -74,18 +67,19 @@ class AddAuditLogUseCaseTest { assertThat(result.isFailure).isTrue() assertThat(result.exceptionOrNull()?.message).isEqualTo("Audit log failed to add") - verify(exactly = 1) { idGenerator.generateId("AUDIT",any(),any()) } + verify(exactly = 1) { idGenerator.generateId("AUDIT", any(), any()) } verify(exactly = 1) { auditRepository.addAuditLog(match { it.id == generatedId }) } } + @Test fun `should return failure when id generator throws exception`() { // Given - every { idGenerator.generateId("AUDIT",any(),any()) } throws IllegalArgumentException("Invalid prefix") + every { idGenerator.generateId("AUDIT", any(), any()) } throws IllegalArgumentException("Invalid prefix") // When val result = addAuditLogUseCase.addAuditLog( - createdBy = User("u1", "TestUser", "ffkjkuyu", UserRole.ADMIN), + createdByUserId = User("u1", "TestUser", "ffkjkuyu", UserRole.ADMIN), auditAction = AuditAction.CREATE, changesDescription = "Created something", entityType = EntityType.TASK, @@ -96,7 +90,9 @@ class AddAuditLogUseCaseTest { assertThat(result.isFailure).isTrue() assertThat(result.exceptionOrNull()?.message).isEqualTo("Audit log failed to add") - verify(exactly = 1) { idGenerator.generateId("AUDIT",any(),any()) } + verify(exactly = 1) { idGenerator.generateId("AUDIT", any(), any()) } verify(exactly = 0) { auditRepository.addAuditLog(any()) } } + + } \ No newline at end of file diff --git a/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCaseTest.kt b/src/test/kotlin/domain/usecase/auditSystem/GetAuditLogsByProjectIdUseCaseTest.kt similarity index 89% rename from src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCaseTest.kt rename to src/test/kotlin/domain/usecase/auditSystem/GetAuditLogsByProjectIdUseCaseTest.kt index 0ac4397..ab73649 100644 --- a/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByProjectIdUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/auditSystem/GetAuditLogsByProjectIdUseCaseTest.kt @@ -1,9 +1,8 @@ -package logic.usecase.auditSystem +package com.berlin.domain.usecase.auditSystem +import com.berlin.domain.model.EntityType import com.berlin.helper.generateAuditLog -import com.berlin.logic.repositories.AuditRepository -import com.berlin.logic.usecase.auditSystem.GetAuditLogsByProjectIdUseCase -import com.berlin.model.EntityType +import com.berlin.domain.repository.AuditRepository import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk diff --git a/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCaseTest.kt b/src/test/kotlin/domain/usecase/auditSystem/GetAuditLogsByTaskIdUseCaseTest.kt similarity index 88% rename from src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCaseTest.kt rename to src/test/kotlin/domain/usecase/auditSystem/GetAuditLogsByTaskIdUseCaseTest.kt index 901a187..4c9a9bb 100644 --- a/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByTaskIdUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/auditSystem/GetAuditLogsByTaskIdUseCaseTest.kt @@ -1,9 +1,8 @@ -package logic.usecase.auditSystem +package com.berlin.domain.usecase.auditSystem +import com.berlin.domain.model.EntityType import com.berlin.helper.generateAuditLog -import com.berlin.logic.repositories.AuditRepository -import com.berlin.logic.usecase.auditSystem.GetAuditLogsByTaskIdUseCase -import com.berlin.model.EntityType +import com.berlin.domain.repository.AuditRepository import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk diff --git a/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCaseTest.kt b/src/test/kotlin/domain/usecase/auditSystem/GetAuditLogsByUserIdUseCaseTest.kt similarity index 92% rename from src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCaseTest.kt rename to src/test/kotlin/domain/usecase/auditSystem/GetAuditLogsByUserIdUseCaseTest.kt index 7750043..568ee0b 100644 --- a/src/test/kotlin/logic/usecase/auditSystem/GetAuditLogsByUserIdUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/auditSystem/GetAuditLogsByUserIdUseCaseTest.kt @@ -1,8 +1,7 @@ -package logic.usecase.auditSystem +package com.berlin.domain.usecase.auditSystem import com.berlin.helper.generateAuditLog -import com.berlin.logic.repositories.AuditRepository -import com.berlin.logic.usecase.auditSystem.GetAuditLogsByUserIdUseCase +import com.berlin.domain.repository.AuditRepository import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk @@ -27,7 +26,7 @@ class GetAuditLogsByUserIdUseCaseTest { // Given val userId = "u1" val logs = listOf( - generateAuditLog(createdBy = generateAuditLog().createdBy) + generateAuditLog(createdBy = generateAuditLog().createdByUserId) ) every { auditRepository.getAuditLogsByUserId(userId) } returns logs diff --git a/src/test/kotlin/helper/auditLogHelper.kt b/src/test/kotlin/helper/auditLogHelper.kt index 1932a70..0ec4b5d 100644 --- a/src/test/kotlin/helper/auditLogHelper.kt +++ b/src/test/kotlin/helper/auditLogHelper.kt @@ -1,6 +1,10 @@ package com.berlin.helper -import com.berlin.model.* +import com.berlin.domain.model.AuditAction +import com.berlin.domain.model.AuditLog +import com.berlin.domain.model.EntityType +import com.berlin.domain.model.UserRole +import com.berlin.domain.model.User fun generateAuditLog( id: String = "A1", @@ -14,7 +18,7 @@ fun generateAuditLog( return AuditLog( id = id, timestamp = timestamp, - createdBy = createdBy, + createdByUserId = createdBy, auditAction = action, changesDescription = changesDescription, entityType = entityType, From 2561a866834a9040aae45340e94c432e3182de8f Mon Sep 17 00:00:00 2001 From: Noha Saad Date: Fri, 2 May 2025 16:33:07 +0300 Subject: [PATCH 4/6] updated the auditLog model and all related files (use case, helper, tests) to use created By UserId as a String instead of a User object --- .../kotlin/domain/usecase/auditSystem/AddAuditLogUseCase.kt | 3 +-- .../domain/usecase/auditSystem/AddAuditLogUseCaseTest.kt | 2 +- src/test/kotlin/helper/auditLogHelper.kt | 4 +--- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/domain/usecase/auditSystem/AddAuditLogUseCase.kt b/src/main/kotlin/domain/usecase/auditSystem/AddAuditLogUseCase.kt index f43a0c4..a38b114 100644 --- a/src/main/kotlin/domain/usecase/auditSystem/AddAuditLogUseCase.kt +++ b/src/main/kotlin/domain/usecase/auditSystem/AddAuditLogUseCase.kt @@ -5,7 +5,6 @@ import com.berlin.domain.model.AuditAction import com.berlin.domain.model.AuditLog import com.berlin.domain.model.EntityType import com.berlin.domain.repository.AuditRepository -import com.berlin.domain.model.User class AddAuditLogUseCase( private val auditRepository: AuditRepository, @@ -13,7 +12,7 @@ class AddAuditLogUseCase( ) { fun addAuditLog( - createdByUserId:User, + createdByUserId:String, auditAction: AuditAction, changesDescription: String, entityType: EntityType, diff --git a/src/test/kotlin/domain/usecase/auditSystem/AddAuditLogUseCaseTest.kt b/src/test/kotlin/domain/usecase/auditSystem/AddAuditLogUseCaseTest.kt index e3eee95..a24379f 100644 --- a/src/test/kotlin/domain/usecase/auditSystem/AddAuditLogUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/auditSystem/AddAuditLogUseCaseTest.kt @@ -79,7 +79,7 @@ class AddAuditLogUseCaseTest { // When val result = addAuditLogUseCase.addAuditLog( - createdByUserId = User("u1", "TestUser", "ffkjkuyu", UserRole.ADMIN), + createdByUserId = "u1", auditAction = AuditAction.CREATE, changesDescription = "Created something", entityType = EntityType.TASK, diff --git a/src/test/kotlin/helper/auditLogHelper.kt b/src/test/kotlin/helper/auditLogHelper.kt index 0ec4b5d..01e8bff 100644 --- a/src/test/kotlin/helper/auditLogHelper.kt +++ b/src/test/kotlin/helper/auditLogHelper.kt @@ -3,13 +3,11 @@ package com.berlin.helper import com.berlin.domain.model.AuditAction import com.berlin.domain.model.AuditLog import com.berlin.domain.model.EntityType -import com.berlin.domain.model.UserRole -import com.berlin.domain.model.User fun generateAuditLog( id: String = "A1", timestamp: Long = System.currentTimeMillis(), - createdBy: User = User("u1", "TestUser", "ffkjkuyu", UserRole.ADMIN), + createdBy: String = "u1", action: AuditAction = AuditAction.CREATE, changesDescription: String? = "Created something", entityType: EntityType = EntityType.TASK, From 9d37ef6d0c618539f5e56be3438b3f568122c74e Mon Sep 17 00:00:00 2001 From: Noha Saad Date: Thu, 15 May 2025 16:52:52 +0300 Subject: [PATCH 5/6] refactor duplicate by make validate function general --- src/main/kotlin/data/UserCache.kt | 1 - src/main/kotlin/di/useCaseModule.kt | 41 ++++++++++--------- .../GetAuditLogsByProjectIdUseCase.kt | 10 ++--- .../GetAuditLogsByTaskIdUseCase.kt | 7 ++-- .../GetAuditLogsByUserIdUseCase.kt | 11 +++-- .../usecase/project/CreateProjectUseCase.kt | 7 ++-- .../usecase/project/DeleteProjectUseCase.kt | 9 ++-- .../usecase/project/GetProjectByIdUseCase.kt | 10 ++--- .../usecase/project/UpdateProjectUseCase.kt | 7 ++-- .../usecase/task/ChangeTaskStateUseCase.kt | 7 ++-- .../domain/usecase/task/CreateTaskUseCase.kt | 10 ++--- .../domain/usecase/task/DeleteTaskUseCase.kt | 6 +-- .../domain/usecase/task/GetTaskByIdUseCase.kt | 7 ++-- .../usecase/task/GetTasksByProjectUseCase.kt | 9 ++-- .../task_state/CreateTaskStateUseCase.kt | 7 ++-- .../task_state/DeleteTaskStateUseCase.kt | 9 ++-- .../GetAllTaskStatesByProjectIdUseCase.kt | 10 ++--- .../task_state/GetTaskStateByIdUseCase.kt | 10 ++--- .../task_state/GetTaskStateByTaskIdUseCase.kt | 9 ++-- .../GetTasksByTaskStateIdUseCase.kt | 6 +-- .../task_state/UpdateTaskStateUseCase.kt | 7 ++-- .../validation/NonBlankNonNumericValidator.kt | 6 +++ .../usecase/utils/validation/Validator.kt | 5 +++ .../GetAuditLogsByProjectIdUseCaseTest.kt | 8 ++-- .../GetAuditLogsByTaskIdUseCaseTest.kt | 5 ++- .../GetAuditLogsByUserIdUseCaseTest.kt | 9 ++-- .../project/CreateProjectUseCaseTest.kt | 5 ++- .../project/DeleteProjectUseCaseTest.kt | 7 +++- .../project/GetProjectByIdUseCaseTest.kt | 6 ++- .../project/UpdateProjectUseCaseTest.kt | 5 ++- .../task/ChangeTaskStateUseCaseTest.kt | 7 +++- .../usecase/task/CreateTaskUseCaseTest.kt | 9 +++- .../usecase/task/DeleteTaskUseCaseTest.kt | 7 +++- .../usecase/task/GetTaskByIdUseCaseTest.kt | 7 +++- .../task/GetTasksByProjectUseCaseTest.kt | 8 +++- .../task_state/CreateTaskStateUseCaseTest.kt | 6 ++- .../task_state/DeleteTaskStateUseCaseTest.kt | 8 +++- .../GetAllTaskStatesByProjectIdUseCaseTest.kt | 6 ++- .../task_state/GetTaskStateByIdUseCaseTest.kt | 6 ++- .../GetTaskStateByTaskIdUseCaseTest.kt | 6 ++- .../GetTasksByTaskStateIdUseCaseTest.kt | 6 ++- .../task_state/UpdateTaskStateUseCaseTest.kt | 6 ++- 42 files changed, 205 insertions(+), 133 deletions(-) create mode 100644 src/main/kotlin/domain/usecase/utils/validation/NonBlankNonNumericValidator.kt create mode 100644 src/main/kotlin/domain/usecase/utils/validation/Validator.kt diff --git a/src/main/kotlin/data/UserCache.kt b/src/main/kotlin/data/UserCache.kt index c691878..7fcc3b3 100644 --- a/src/main/kotlin/data/UserCache.kt +++ b/src/main/kotlin/data/UserCache.kt @@ -6,7 +6,6 @@ import com.berlin.data.mapper.UserMapper import com.berlin.domain.model.Permission import com.berlin.domain.model.user.User import com.berlin.domain.permission.assignPermissions -import com.berlin.domain.repository.AuthenticationRepository class UserCache( user: User, diff --git a/src/main/kotlin/di/useCaseModule.kt b/src/main/kotlin/di/useCaseModule.kt index f2b42a5..5b09575 100644 --- a/src/main/kotlin/di/useCaseModule.kt +++ b/src/main/kotlin/di/useCaseModule.kt @@ -18,30 +18,33 @@ import com.berlin.domain.usecase.task_state.GetTaskStateByIdUseCase import com.berlin.domain.usecase.task_state.GetTaskStateByTaskIdUseCase import com.berlin.domain.usecase.task_state.GetTasksByTaskStateIdUseCase import com.berlin.domain.usecase.task_state.UpdateTaskStateUseCase +import com.berlin.domain.usecase.utils.validation.NonBlankNonNumericValidator +import com.berlin.domain.usecase.utils.validation.Validator import data.UserCache import domain.usecase.auth_service.LoginUserUseCase import org.koin.dsl.module val useCaseModule = module { - single { CreateTaskUseCase(get(), get(), get()) } + single { NonBlankNonNumericValidator() } + single { CreateTaskUseCase(get(), get(), get(),get()) } single { AssignTaskUseCase(get(), get(), get()) } - single { DeleteTaskUseCase(get(), get(), get()) } - single { GetTasksByProjectUseCase(get()) } + single { DeleteTaskUseCase(get(), get(), get(),get()) } + single { GetTasksByProjectUseCase(get(),get()) } single { UpdateTaskUseCase(get(), get(), get()) } - single { ChangeTaskStateUseCase(get(), get(), get()) } - single { GetTaskByIdUseCase(get()) } + single { ChangeTaskStateUseCase(get(), get(), get(),get()) } + single { GetTaskByIdUseCase(get(),get()) } single { GetAllTasksUseCase(get()) } - single { CreateProjectUseCase(get(), get(), get(), get()) } + single { CreateProjectUseCase(get(), get(), get(), get(),get()) } single { GetAllProjectsUseCase(get()) } - single { DeleteProjectUseCase(get(), get(), get()) } - single { GetProjectByIdUseCase(get()) } - single { UpdateProjectUseCase(get(), get(), get() ) } + single { DeleteProjectUseCase(get(), get(), get(),get()) } + single { GetProjectByIdUseCase(get(),get()) } + single { UpdateProjectUseCase(get(), get(), get(),get() ) } single { AddAuditLogUseCase(get(), get()) } - single { GetAuditLogsByProjectIdUseCase(get()) } - single { GetAuditLogsByTaskIdUseCase(get()) } - single { GetAuditLogsByUserIdUseCase(get()) } + single { GetAuditLogsByProjectIdUseCase(get(),get()) } + single { GetAuditLogsByTaskIdUseCase(get(),get())} + single { GetAuditLogsByUserIdUseCase(get(),get())} single { GetUserByIDUseCase(get()) } single { GetUserLoggedInUseCase(get()) } @@ -49,12 +52,12 @@ val useCaseModule = module { single { LoginUserUseCase(get(),get(), get()) } single { CreateMateUseCase(get(), get(), get()) } - single { CreateTaskStateUseCase(get(), get()) } - single { DeleteTaskStateUseCase(get()) } - single { GetAllTaskStatesByProjectIdUseCase(get(), get()) } - single { GetTaskStateByIdUseCase(get()) } - single { GetTaskStateByTaskIdUseCase(get(), get()) } - single { GetTasksByTaskStateIdUseCase(get()) } - single { UpdateTaskStateUseCase(get()) } + single { CreateTaskStateUseCase(get(), get(),get()) } + single { DeleteTaskStateUseCase(get(),get()) } + single { GetAllTaskStatesByProjectIdUseCase(get(), get(),get()) } + single { GetTaskStateByIdUseCase(get(),get()) } + single { GetTaskStateByTaskIdUseCase(get(), get(),get()) } + single { GetTasksByTaskStateIdUseCase(get(),get()) } + single { UpdateTaskStateUseCase(get(),get()) } single { GetAllTaskStatesUseCase(get()) } } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/audit_system/GetAuditLogsByProjectIdUseCase.kt b/src/main/kotlin/domain/usecase/audit_system/GetAuditLogsByProjectIdUseCase.kt index be710be..a56d7cb 100644 --- a/src/main/kotlin/domain/usecase/audit_system/GetAuditLogsByProjectIdUseCase.kt +++ b/src/main/kotlin/domain/usecase/audit_system/GetAuditLogsByProjectIdUseCase.kt @@ -3,19 +3,19 @@ package com.berlin.domain.usecase.audit_system import com.berlin.domain.exception.InvalidProjectIdException import com.berlin.domain.model.AuditLog import com.berlin.domain.repository.AuditRepository +import com.berlin.domain.usecase.utils.validation.Validator + class GetAuditLogsByProjectIdUseCase( - private val auditRepository: AuditRepository + private val auditRepository: AuditRepository, + private val validator: Validator ) { operator fun invoke(projectId: String): List { - if (!validateProjectId(projectId)) + if (!validator.isValid(projectId)) throw InvalidProjectIdException("Project ID must not be empty, blank, or purely numeric") return auditRepository.getAuditLogsByProjectId(projectId) } - - private fun validateProjectId(projectId: String): Boolean = - projectId.isNotBlank() && !(projectId.all { it.isDigit() }) } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/audit_system/GetAuditLogsByTaskIdUseCase.kt b/src/main/kotlin/domain/usecase/audit_system/GetAuditLogsByTaskIdUseCase.kt index 22b209e..0e45195 100644 --- a/src/main/kotlin/domain/usecase/audit_system/GetAuditLogsByTaskIdUseCase.kt +++ b/src/main/kotlin/domain/usecase/audit_system/GetAuditLogsByTaskIdUseCase.kt @@ -3,17 +3,18 @@ package com.berlin.domain.usecase.audit_system import com.berlin.domain.exception.InvalidTaskIdException import com.berlin.domain.model.AuditLog import com.berlin.domain.repository.AuditRepository +import com.berlin.domain.usecase.utils.validation.Validator class GetAuditLogsByTaskIdUseCase( private val auditRepository: AuditRepository, + private val validator: Validator ) { operator fun invoke(taskId: String): List { - if (!validateTaskId(taskId)) throw InvalidTaskIdException("Task ID must not be empty, blank, or purely numeric") + if (!validator.isValid(taskId)) + throw InvalidTaskIdException("Task ID must not be empty, blank, or purely numeric") return auditRepository.getAuditLogsByTaskId(taskId) } - - private fun validateTaskId(projectId: String): Boolean = projectId.isNotBlank() && !(projectId.all { it.isDigit() }) } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/audit_system/GetAuditLogsByUserIdUseCase.kt b/src/main/kotlin/domain/usecase/audit_system/GetAuditLogsByUserIdUseCase.kt index 92508c7..3cbc87e 100644 --- a/src/main/kotlin/domain/usecase/audit_system/GetAuditLogsByUserIdUseCase.kt +++ b/src/main/kotlin/domain/usecase/audit_system/GetAuditLogsByUserIdUseCase.kt @@ -3,20 +3,19 @@ package com.berlin.domain.usecase.audit_system import com.berlin.domain.exception.InvalidUserIdException import com.berlin.domain.model.AuditLog import com.berlin.domain.repository.AuditRepository +import com.berlin.domain.usecase.utils.validation.Validator class GetAuditLogsByUserIdUseCase( - private val auditRepository: AuditRepository + private val auditRepository: AuditRepository, + private val validator: Validator ) { - operator fun invoke(userId:String): List{ + operator fun invoke(userId: String): List { - if (!validateUserId(userId)) + if (!validator.isValid(userId)) throw InvalidUserIdException("User ID must not be empty, blank, or purely numeric") return auditRepository.getAuditLogsByUserId(userId) } - - private fun validateUserId(projectId: String): Boolean = - projectId.isNotBlank() && !(projectId.all { it.isDigit() }) } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/project/CreateProjectUseCase.kt b/src/main/kotlin/domain/usecase/project/CreateProjectUseCase.kt index 468144a..af016cd 100644 --- a/src/main/kotlin/domain/usecase/project/CreateProjectUseCase.kt +++ b/src/main/kotlin/domain/usecase/project/CreateProjectUseCase.kt @@ -5,6 +5,7 @@ import com.berlin.domain.model.Project import com.berlin.domain.repository.ProjectRepository import com.berlin.domain.usecase.audit_system.AddAuditLogUseCase import com.berlin.domain.usecase.utils.id_generator.IdGenerator +import com.berlin.domain.usecase.utils.validation.Validator import data.UserCache class CreateProjectUseCase( @@ -12,6 +13,7 @@ class CreateProjectUseCase( private val idGenerator: IdGenerator, private val addAuditLogUseCase: AddAuditLogUseCase, private val cashedUser: UserCache, + private val validator: Validator ) { operator fun invoke( projectName: String, @@ -19,7 +21,7 @@ class CreateProjectUseCase( stateId: List?, taskId: List?, ): String { - if (validateProjectName(projectName)) { + if (validator.isValid(projectName)) { val newProject = Project( id = idGenerator.generateId(projectName), title = projectName, @@ -42,7 +44,4 @@ class CreateProjectUseCase( throw Exception("Project Name must not be empty or blank") } } - - private fun validateProjectName(projectName: String): Boolean = - projectName.isNotBlank() && !(projectName.all { it.isDigit() }) } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/project/DeleteProjectUseCase.kt b/src/main/kotlin/domain/usecase/project/DeleteProjectUseCase.kt index e7f1833..b74b351 100644 --- a/src/main/kotlin/domain/usecase/project/DeleteProjectUseCase.kt +++ b/src/main/kotlin/domain/usecase/project/DeleteProjectUseCase.kt @@ -1,20 +1,21 @@ package com.berlin.domain.usecase.project import com.berlin.domain.exception.InvalidProjectIdException -import com.berlin.domain.exception.ProjectNotFoundException import com.berlin.domain.model.AuditLog import com.berlin.domain.repository.ProjectRepository import com.berlin.domain.usecase.audit_system.AddAuditLogUseCase +import com.berlin.domain.usecase.utils.validation.Validator import data.UserCache class DeleteProjectUseCase( private val projectRepository: ProjectRepository, private val addAuditLogUseCase: AddAuditLogUseCase, private val cashedUser: UserCache, + private val validator: Validator ) { operator fun invoke(projectId: String): String { - if (!validateProjectId(projectId)) { + if (!validator.isValid(projectId)) { throw InvalidProjectIdException("Project ID must not be empty or blank") } @@ -29,8 +30,4 @@ class DeleteProjectUseCase( return deletedProject } - - private fun validateProjectId(projectId: String): Boolean = - projectId.isNotBlank() && !(projectId.all { it.isDigit() }) - } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/project/GetProjectByIdUseCase.kt b/src/main/kotlin/domain/usecase/project/GetProjectByIdUseCase.kt index 75255d3..85b57cb 100644 --- a/src/main/kotlin/domain/usecase/project/GetProjectByIdUseCase.kt +++ b/src/main/kotlin/domain/usecase/project/GetProjectByIdUseCase.kt @@ -3,19 +3,17 @@ package com.berlin.domain.usecase.project import com.berlin.domain.exception.InvalidProjectIdException import com.berlin.domain.repository.ProjectRepository import com.berlin.domain.model.Project +import com.berlin.domain.usecase.utils.validation.Validator class GetProjectByIdUseCase ( - private val projectRepository: ProjectRepository + private val projectRepository: ProjectRepository, + private val validator: Validator ) { operator fun invoke(projectId: String): Project { - if(!validateProjectId(projectId)) + if(!validator.isValid(projectId)) throw InvalidProjectIdException("project id must not be empty, blank, or purely numeric") return projectRepository.getProjectById(projectId) } - - private fun validateProjectId(projectId: String): Boolean = - projectId.isNotBlank() && !(projectId.all { it.isDigit() }) - } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/project/UpdateProjectUseCase.kt b/src/main/kotlin/domain/usecase/project/UpdateProjectUseCase.kt index 14bd1b4..a6ea810 100644 --- a/src/main/kotlin/domain/usecase/project/UpdateProjectUseCase.kt +++ b/src/main/kotlin/domain/usecase/project/UpdateProjectUseCase.kt @@ -5,15 +5,17 @@ import com.berlin.domain.model.AuditLog import com.berlin.domain.model.Project import com.berlin.domain.repository.ProjectRepository import com.berlin.domain.usecase.audit_system.AddAuditLogUseCase +import com.berlin.domain.usecase.utils.validation.Validator import data.UserCache class UpdateProjectUseCase( private val projectRepository: ProjectRepository, private val addAuditLogUseCase: AddAuditLogUseCase, private val cashedUser: UserCache, + private val validator: Validator ) { operator fun invoke(project: Project): String { - if (!validateProjectName(project.title)) throw InvalidProjectException("Project Name must not be empty or blank") + if (!validator.isValid(project.title)) throw InvalidProjectException("Project Name must not be empty or blank") val updatedProject = projectRepository.updateProject(project) @@ -26,7 +28,4 @@ class UpdateProjectUseCase( return updatedProject } - - private fun validateProjectName(projectName: String): Boolean = - projectName.isNotBlank() && !(projectName.all { it.isDigit() }) } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/task/ChangeTaskStateUseCase.kt b/src/main/kotlin/domain/usecase/task/ChangeTaskStateUseCase.kt index 76349fc..33ae13f 100644 --- a/src/main/kotlin/domain/usecase/task/ChangeTaskStateUseCase.kt +++ b/src/main/kotlin/domain/usecase/task/ChangeTaskStateUseCase.kt @@ -5,19 +5,21 @@ import com.berlin.domain.model.AuditLog import com.berlin.domain.model.Task import com.berlin.domain.repository.TaskRepository import com.berlin.domain.usecase.audit_system.AddAuditLogUseCase +import com.berlin.domain.usecase.utils.validation.Validator import data.UserCache class ChangeTaskStateUseCase( private val taskRepository: TaskRepository, private val addAuditLogUseCase: AddAuditLogUseCase, private val cashedUser: UserCache, + private val validator: Validator ) { operator fun invoke(taskId: String, newStateId: String): Task { val original = taskRepository.getTaskById(taskId) - if (!validateStateId(newStateId)) { + if (!validator.isValid(newStateId)) { throw InvalidTaskStateException("State id must not be empty, blank, or purely numeric") } @@ -33,7 +35,4 @@ class ChangeTaskStateUseCase( return updatedTask } - - private fun validateStateId(stateId: String): Boolean = - stateId.isNotBlank() && !stateId.all { it.isDigit() } } diff --git a/src/main/kotlin/domain/usecase/task/CreateTaskUseCase.kt b/src/main/kotlin/domain/usecase/task/CreateTaskUseCase.kt index 2441fe4..09a194a 100644 --- a/src/main/kotlin/domain/usecase/task/CreateTaskUseCase.kt +++ b/src/main/kotlin/domain/usecase/task/CreateTaskUseCase.kt @@ -7,11 +7,13 @@ import com.berlin.domain.model.Task import com.berlin.domain.repository.TaskRepository import com.berlin.domain.usecase.audit_system.AddAuditLogUseCase import com.berlin.domain.usecase.utils.id_generator.IdGenerator +import com.berlin.domain.usecase.utils.validation.Validator class CreateTaskUseCase( private val taskRepository: TaskRepository, private val defaultIdGenerator: IdGenerator, - private val addAuditLogUseCase: AddAuditLogUseCase + private val addAuditLogUseCase: AddAuditLogUseCase, + private val validator: Validator ) { operator fun invoke( projectId: String, @@ -21,7 +23,7 @@ class CreateTaskUseCase( createByUserId: String, assignedToUserId: String, ): Task { - if (validateTaskTitle(title.trim())) { + if (validator.isValid(title.trim())) { val newTask = Task( id = defaultIdGenerator.generateId(title.trim()), projectId = projectId, @@ -50,10 +52,6 @@ class CreateTaskUseCase( } } - private fun validateTaskTitle(title: String): Boolean { - return title.isNotBlank() && !title.any { it.isDigit() } - } - private fun validateUniqueTask(taskId: String): Boolean { return try { taskRepository.getTaskById(taskId) diff --git a/src/main/kotlin/domain/usecase/task/DeleteTaskUseCase.kt b/src/main/kotlin/domain/usecase/task/DeleteTaskUseCase.kt index 2e8658d..562cefc 100644 --- a/src/main/kotlin/domain/usecase/task/DeleteTaskUseCase.kt +++ b/src/main/kotlin/domain/usecase/task/DeleteTaskUseCase.kt @@ -3,15 +3,17 @@ package com.berlin.domain.usecase.task import com.berlin.domain.model.AuditLog import com.berlin.domain.repository.TaskRepository import com.berlin.domain.usecase.audit_system.AddAuditLogUseCase +import com.berlin.domain.usecase.utils.validation.Validator import data.UserCache class DeleteTaskUseCase( private val taskRepository: TaskRepository, private val addAuditLogUseCase: AddAuditLogUseCase, private val cashedUser: UserCache, + private val validator: Validator ) { operator fun invoke(taskId: String) : String { - if (!validateTaskId(taskId)) { + if (!validator.isValid(taskId)) { throw Exception("Project ID must not be empty or blank") } taskRepository.deleteTask(taskId) @@ -25,6 +27,4 @@ class DeleteTaskUseCase( return "Deleted." } - - private fun validateTaskId(taskId: String): Boolean = taskId.isNotBlank() && !(taskId.all { it.isDigit() }) } diff --git a/src/main/kotlin/domain/usecase/task/GetTaskByIdUseCase.kt b/src/main/kotlin/domain/usecase/task/GetTaskByIdUseCase.kt index 97e6080..f8dffc7 100644 --- a/src/main/kotlin/domain/usecase/task/GetTaskByIdUseCase.kt +++ b/src/main/kotlin/domain/usecase/task/GetTaskByIdUseCase.kt @@ -3,20 +3,19 @@ package com.berlin.domain.usecase.task import com.berlin.domain.exception.InvalidTaskIdException import com.berlin.domain.model.Task import com.berlin.domain.repository.TaskRepository +import com.berlin.domain.usecase.utils.validation.Validator class GetTaskByIdUseCase( private val taskRepository: TaskRepository, + private val validator: Validator ) { operator fun invoke(taskId: String): Task { - if (!validateTaskId(taskId)) { + if (!validator.isValid(taskId)) { throw InvalidTaskIdException("Task id must not be empty, blank, or purely numeric") } return taskRepository.getTaskById(taskId) } - - private fun validateTaskId(id: String): Boolean = - id.isNotBlank() && !id.all { it.isDigit() } } diff --git a/src/main/kotlin/domain/usecase/task/GetTasksByProjectUseCase.kt b/src/main/kotlin/domain/usecase/task/GetTasksByProjectUseCase.kt index 8ab6b7b..23a15f4 100644 --- a/src/main/kotlin/domain/usecase/task/GetTasksByProjectUseCase.kt +++ b/src/main/kotlin/domain/usecase/task/GetTasksByProjectUseCase.kt @@ -3,19 +3,18 @@ package com.berlin.domain.usecase.task import com.berlin.domain.exception.InvalidProjectIdException import com.berlin.domain.model.Task import com.berlin.domain.repository.TaskRepository +import com.berlin.domain.usecase.utils.validation.Validator class GetTasksByProjectUseCase( - private val taskRepository: TaskRepository + private val taskRepository: TaskRepository, + private val validator: Validator ) { operator fun invoke(projectId: String): List { - if (!validateProjectId(projectId)) { + if (!validator.isValid(projectId)) { throw InvalidProjectIdException("Project id must not be empty, blank, or purely numeric") } return taskRepository.getTasksByProjectId(projectId) } - - private fun validateProjectId(id: String): Boolean = - id.isNotBlank() && !id.all { it.isDigit() } } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/task_state/CreateTaskStateUseCase.kt b/src/main/kotlin/domain/usecase/task_state/CreateTaskStateUseCase.kt index 99bd0d5..5180a30 100644 --- a/src/main/kotlin/domain/usecase/task_state/CreateTaskStateUseCase.kt +++ b/src/main/kotlin/domain/usecase/task_state/CreateTaskStateUseCase.kt @@ -5,13 +5,15 @@ import com.berlin.domain.exception.InvalidStateNameException import com.berlin.domain.repository.TaskStateRepository import com.berlin.domain.model.TaskState import com.berlin.domain.usecase.utils.id_generator.IdGeneratorImplementation +import com.berlin.domain.usecase.utils.validation.Validator class CreateTaskStateUseCase( private val taskStateRepository: TaskStateRepository, private val idGenerator: IdGeneratorImplementation, + private val validator: Validator ) { operator fun invoke(stateName: String, projectId: String): String { - if (validateStateName(stateName)) { + if (validator.isValid(stateName)) { val newState = TaskState( id = idGenerator.generateId(stateName), name = stateName, @@ -22,7 +24,4 @@ class CreateTaskStateUseCase( throw InvalidStateNameException("State Name must not be empty or blank") } } - - private fun validateStateName(stateName: String): Boolean = - stateName.isNotBlank() && !(stateName.all { it.isDigit() }) } diff --git a/src/main/kotlin/domain/usecase/task_state/DeleteTaskStateUseCase.kt b/src/main/kotlin/domain/usecase/task_state/DeleteTaskStateUseCase.kt index 0c62942..af5c347 100644 --- a/src/main/kotlin/domain/usecase/task_state/DeleteTaskStateUseCase.kt +++ b/src/main/kotlin/domain/usecase/task_state/DeleteTaskStateUseCase.kt @@ -2,19 +2,18 @@ package com.berlin.domain.usecase.task_state import com.berlin.domain.exception.InvalidStateIdException import com.berlin.domain.repository.TaskStateRepository +import com.berlin.domain.usecase.utils.validation.Validator class DeleteTaskStateUseCase( - private val taskStateRepository: TaskStateRepository + private val taskStateRepository: TaskStateRepository, + private val validator: Validator ) { operator fun invoke(stateId: String): String { - if(!validateStateId(stateId)) + if(!validator.isValid(stateId)) throw InvalidStateIdException("State ID must not be empty or blank") return taskStateRepository.deleteState(stateId) } - - private fun validateStateId(stateId: String): Boolean = - stateId.isNotBlank() && !(stateId.all { it.isDigit() }) } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/task_state/GetAllTaskStatesByProjectIdUseCase.kt b/src/main/kotlin/domain/usecase/task_state/GetAllTaskStatesByProjectIdUseCase.kt index 6770dc9..6a8c702 100644 --- a/src/main/kotlin/domain/usecase/task_state/GetAllTaskStatesByProjectIdUseCase.kt +++ b/src/main/kotlin/domain/usecase/task_state/GetAllTaskStatesByProjectIdUseCase.kt @@ -5,15 +5,17 @@ import com.berlin.domain.exception.InvalidProjectIdException import com.berlin.domain.model.TaskState import com.berlin.domain.repository.ProjectRepository import com.berlin.domain.repository.TaskStateRepository +import com.berlin.domain.usecase.utils.validation.Validator class GetAllTaskStatesByProjectIdUseCase( private val taskStateRepository: TaskStateRepository, - private val projectRepository: ProjectRepository + private val projectRepository: ProjectRepository, + private val validator: Validator ) { operator fun invoke(projectId: String): List { - return if (!validateProjectId(projectId)) { + return if (!validator.isValid(projectId)) { throw InvalidProjectIdException("Project ID must not be empty or blank") } else { @@ -21,8 +23,4 @@ class GetAllTaskStatesByProjectIdUseCase( } } - - private fun validateProjectId(projectId: String): Boolean = - projectId.isNotBlank() && !(projectId.all { it.isDigit() }) - } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/task_state/GetTaskStateByIdUseCase.kt b/src/main/kotlin/domain/usecase/task_state/GetTaskStateByIdUseCase.kt index 5ba37fa..9804991 100644 --- a/src/main/kotlin/domain/usecase/task_state/GetTaskStateByIdUseCase.kt +++ b/src/main/kotlin/domain/usecase/task_state/GetTaskStateByIdUseCase.kt @@ -3,19 +3,17 @@ package com.berlin.domain.usecase.task_state import com.berlin.domain.exception.InvalidStateIdException import com.berlin.domain.model.TaskState import com.berlin.domain.repository.TaskStateRepository +import com.berlin.domain.usecase.utils.validation.Validator class GetTaskStateByIdUseCase( - private val taskStateRepository: TaskStateRepository + private val taskStateRepository: TaskStateRepository, + private val validator: Validator ) { operator fun invoke(stateId: String): TaskState { - if(!validateStateId(stateId)) + if(!validator.isValid(stateId)) throw InvalidStateIdException("State id must not be empty, blank, or purely numeric") return taskStateRepository.getStateById(stateId) } - - private fun validateStateId(stateId: String): Boolean = - stateId.isNotBlank() && !(stateId.all { it.isDigit() }) - } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/task_state/GetTaskStateByTaskIdUseCase.kt b/src/main/kotlin/domain/usecase/task_state/GetTaskStateByTaskIdUseCase.kt index 2bf1541..7b43a95 100644 --- a/src/main/kotlin/domain/usecase/task_state/GetTaskStateByTaskIdUseCase.kt +++ b/src/main/kotlin/domain/usecase/task_state/GetTaskStateByTaskIdUseCase.kt @@ -4,21 +4,20 @@ import com.berlin.domain.exception.InvalidTaskIdException import com.berlin.domain.model.TaskState import com.berlin.domain.repository.TaskStateRepository import com.berlin.domain.repository.TaskRepository +import com.berlin.domain.usecase.utils.validation.Validator class GetTaskStateByTaskIdUseCase( private val taskStateRepository: TaskStateRepository, - private val taskRepository: TaskRepository + private val taskRepository: TaskRepository, + private val validator: Validator ) { operator fun invoke(taskId: String): TaskState? { - if (!validateTaskId(taskId)) { + if (!validator.isValid(taskId)) { throw InvalidTaskIdException("Task ID must not be empty or blank") } else { return taskStateRepository.getStateByTaskId(taskId) } } - - private fun validateTaskId(taskId: String): Boolean = taskId.isNotBlank() && !(taskId.all { it.isDigit() }) - } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/task_state/GetTasksByTaskStateIdUseCase.kt b/src/main/kotlin/domain/usecase/task_state/GetTasksByTaskStateIdUseCase.kt index e3c909b..d40e886 100644 --- a/src/main/kotlin/domain/usecase/task_state/GetTasksByTaskStateIdUseCase.kt +++ b/src/main/kotlin/domain/usecase/task_state/GetTasksByTaskStateIdUseCase.kt @@ -4,19 +4,19 @@ import com.berlin.domain.exception.InvalidStateIdException import com.berlin.domain.exception.TaskNotFoundException import com.berlin.domain.model.Task import com.berlin.domain.repository.TaskStateRepository +import com.berlin.domain.usecase.utils.validation.Validator class GetTasksByTaskStateIdUseCase( private val taskStateRepository: TaskStateRepository, + private val validator: Validator ) { operator fun invoke(stateId: String): List { - if (!validateStateId(stateId)) { + if (!validator.isValid(stateId)) { throw InvalidStateIdException("State ID must not be empty or blank") } else { return taskStateRepository.getTasksByStateId(stateId) ?: throw TaskNotFoundException("No tasks found for state ID $stateId") } } - - private fun validateStateId(stateId: String): Boolean = stateId.isNotBlank() && !(stateId.all { it.isDigit() }) } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/task_state/UpdateTaskStateUseCase.kt b/src/main/kotlin/domain/usecase/task_state/UpdateTaskStateUseCase.kt index 6e17b0b..aa44caa 100644 --- a/src/main/kotlin/domain/usecase/task_state/UpdateTaskStateUseCase.kt +++ b/src/main/kotlin/domain/usecase/task_state/UpdateTaskStateUseCase.kt @@ -3,12 +3,14 @@ package com.berlin.domain.usecase.task_state import com.berlin.domain.exception.InvalidStateNameException import com.berlin.domain.model.TaskState import com.berlin.domain.repository.TaskStateRepository +import com.berlin.domain.usecase.utils.validation.Validator class UpdateTaskStateUseCase( private val taskStateRepository: TaskStateRepository, + private val validator: Validator ) { operator fun invoke(stateId: String, newStateName: String, projectId: String): String { - if (!validateStateName(newStateName)) + if (!validator.isValid(newStateName)) throw InvalidStateNameException("State Name must not be empty or blank") val updatedState = TaskState( id = stateId, @@ -18,7 +20,4 @@ class UpdateTaskStateUseCase( return taskStateRepository.updateState(updatedState) } - - private fun validateStateName(stateName: String): Boolean = - stateName.isNotBlank() && !(stateName.all { it.isDigit() }) } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/utils/validation/NonBlankNonNumericValidator.kt b/src/main/kotlin/domain/usecase/utils/validation/NonBlankNonNumericValidator.kt new file mode 100644 index 0000000..56b8b76 --- /dev/null +++ b/src/main/kotlin/domain/usecase/utils/validation/NonBlankNonNumericValidator.kt @@ -0,0 +1,6 @@ +package com.berlin.domain.usecase.utils.validation + +class NonBlankNonNumericValidator : Validator{ + override fun isValid(input: String): Boolean = + input.isNotBlank() && !(input.all {it.isDigit()}) + } \ No newline at end of file diff --git a/src/main/kotlin/domain/usecase/utils/validation/Validator.kt b/src/main/kotlin/domain/usecase/utils/validation/Validator.kt new file mode 100644 index 0000000..e3adda9 --- /dev/null +++ b/src/main/kotlin/domain/usecase/utils/validation/Validator.kt @@ -0,0 +1,5 @@ +package com.berlin.domain.usecase.utils.validation + +interface Validator { + fun isValid(input: String):Boolean +} \ No newline at end of file diff --git a/src/test/kotlin/domain/usecase/audit_system/GetAuditLogsByProjectIdUseCaseTest.kt b/src/test/kotlin/domain/usecase/audit_system/GetAuditLogsByProjectIdUseCaseTest.kt index 85e55e8..e47d42e 100644 --- a/src/test/kotlin/domain/usecase/audit_system/GetAuditLogsByProjectIdUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/audit_system/GetAuditLogsByProjectIdUseCaseTest.kt @@ -1,10 +1,10 @@ -package com.berlin.domain.usecase.auditSystem +package com.berlin.domain.usecase.audit_system import com.berlin.domain.exception.InvalidProjectIdException import com.berlin.domain.model.AuditLog import com.berlin.helper.generateAuditLog import com.berlin.domain.repository.AuditRepository -import com.berlin.domain.usecase.audit_system.GetAuditLogsByProjectIdUseCase +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk @@ -18,11 +18,12 @@ import org.junit.jupiter.params.provider.ValueSource class GetAuditLogsByProjectIdUseCaseTest { private val auditRepository: AuditRepository = mockk(relaxed = true) + private val validator:Validator= mockk(relaxed = true) private lateinit var getAuditLogsByProjectIdUseCase: GetAuditLogsByProjectIdUseCase @BeforeEach fun setup() { - getAuditLogsByProjectIdUseCase = GetAuditLogsByProjectIdUseCase(auditRepository) + getAuditLogsByProjectIdUseCase = GetAuditLogsByProjectIdUseCase(auditRepository, validator ) } @Test @@ -32,6 +33,7 @@ class GetAuditLogsByProjectIdUseCaseTest { val logs = listOf( generateAuditLog(id = "A2", entityId = projectId, entityType = AuditLog.EntityType.PROJECT) ) + every { validator.isValid(projectId) } returns true every { auditRepository.getAuditLogsByProjectId(projectId) } returns logs //When diff --git a/src/test/kotlin/domain/usecase/audit_system/GetAuditLogsByTaskIdUseCaseTest.kt b/src/test/kotlin/domain/usecase/audit_system/GetAuditLogsByTaskIdUseCaseTest.kt index b62edb4..27643b8 100644 --- a/src/test/kotlin/domain/usecase/audit_system/GetAuditLogsByTaskIdUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/audit_system/GetAuditLogsByTaskIdUseCaseTest.kt @@ -5,6 +5,7 @@ import com.berlin.domain.model.AuditLog import com.berlin.helper.generateAuditLog import com.berlin.domain.repository.AuditRepository import com.berlin.domain.usecase.audit_system.GetAuditLogsByTaskIdUseCase +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk @@ -16,11 +17,12 @@ import org.junit.jupiter.params.provider.ValueSource class GetAuditLogsByTaskIdUseCaseTest { private val auditRepository: AuditRepository = mockk(relaxed = true) + private val validator: Validator = mockk(relaxed = true) private lateinit var getAuditLogsByTaskIdUseCase: GetAuditLogsByTaskIdUseCase @BeforeEach fun setup() { - getAuditLogsByTaskIdUseCase = GetAuditLogsByTaskIdUseCase(auditRepository) + getAuditLogsByTaskIdUseCase = GetAuditLogsByTaskIdUseCase(auditRepository,validator) } @Test @@ -30,6 +32,7 @@ class GetAuditLogsByTaskIdUseCaseTest { val logs = listOf( generateAuditLog(id = "A3", entityId = taskId, entityType = AuditLog.EntityType.TASK) ) + every { validator.isValid(taskId) } returns true every { auditRepository.getAuditLogsByTaskId(taskId) } returns logs //When diff --git a/src/test/kotlin/domain/usecase/audit_system/GetAuditLogsByUserIdUseCaseTest.kt b/src/test/kotlin/domain/usecase/audit_system/GetAuditLogsByUserIdUseCaseTest.kt index 664d2eb..5ee4c96 100644 --- a/src/test/kotlin/domain/usecase/audit_system/GetAuditLogsByUserIdUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/audit_system/GetAuditLogsByUserIdUseCaseTest.kt @@ -1,9 +1,9 @@ -package com.berlin.domain.usecase.auditSystem +package com.berlin.domain.usecase.audit_system import com.berlin.domain.exception.InvalidUserIdException import com.berlin.helper.generateAuditLog import com.berlin.domain.repository.AuditRepository -import com.berlin.domain.usecase.audit_system.GetAuditLogsByUserIdUseCase +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk @@ -16,11 +16,12 @@ import org.junit.jupiter.params.provider.ValueSource class GetAuditLogsByUserIdUseCaseTest { private val auditRepository: AuditRepository = mockk(relaxed = true) + private val validator: Validator = mockk(relaxed = true) private lateinit var getAuditLogsByUserIdUseCase: GetAuditLogsByUserIdUseCase @BeforeEach fun setup() { - getAuditLogsByUserIdUseCase = GetAuditLogsByUserIdUseCase(auditRepository) + getAuditLogsByUserIdUseCase = GetAuditLogsByUserIdUseCase(auditRepository,validator) } @Test @@ -30,6 +31,7 @@ class GetAuditLogsByUserIdUseCaseTest { val logs = listOf( generateAuditLog(createdBy = generateAuditLog().createdByUserId) ) + every { validator.isValid(userId) } returns true every { auditRepository.getAuditLogsByUserId(userId) } returns logs //When @@ -45,6 +47,7 @@ class GetAuditLogsByUserIdUseCaseTest { fun `should return empty list when no audit logs found for user ID`() { // Given val userId = "invalid" + every { validator.isValid(userId) } returns true every { auditRepository.getAuditLogsByUserId(userId) } returns emptyList() //When diff --git a/src/test/kotlin/domain/usecase/project/CreateProjectUseCaseTest.kt b/src/test/kotlin/domain/usecase/project/CreateProjectUseCaseTest.kt index 8943396..a99045f 100644 --- a/src/test/kotlin/domain/usecase/project/CreateProjectUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/project/CreateProjectUseCaseTest.kt @@ -4,6 +4,7 @@ import com.berlin.domain.exception.InvalidProjectException import com.berlin.domain.repository.ProjectRepository import com.berlin.domain.usecase.audit_system.AddAuditLogUseCase import com.berlin.domain.usecase.utils.id_generator.IdGenerator +import com.berlin.domain.usecase.utils.validation.Validator import com.berlin.helper.projectHelper import com.google.common.truth.Truth.assertThat import data.UserCache @@ -22,17 +23,19 @@ class CreateProjectUseCaseTest { private val projectRepository: ProjectRepository = mockk(relaxed = true) private val addAuditLogUseCase: AddAuditLogUseCase = mockk(relaxed = true) private val cashedUser: UserCache = mockk(relaxed = true) + private val validator: Validator = mockk(relaxed = true) @BeforeEach fun setup() { val idGenerator: IdGenerator = mockk(relaxed = true) - createProjectUseCase = CreateProjectUseCase(projectRepository, idGenerator, addAuditLogUseCase, cashedUser) + createProjectUseCase = CreateProjectUseCase(projectRepository, idGenerator, addAuditLogUseCase, cashedUser,validator) } @Test fun `createNewProject should log audit when project is created successfully`() { // Given val validProject = projectHelper() + every { validator.isValid(any()) } returns true every { projectRepository.createProject(any()) } returns "Creation Successfully" every { cashedUser.currentUser.id } returns "user_123" diff --git a/src/test/kotlin/domain/usecase/project/DeleteProjectUseCaseTest.kt b/src/test/kotlin/domain/usecase/project/DeleteProjectUseCaseTest.kt index c1b6a17..04d23eb 100644 --- a/src/test/kotlin/domain/usecase/project/DeleteProjectUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/project/DeleteProjectUseCaseTest.kt @@ -3,6 +3,7 @@ package com.berlin.domain.usecase.project import com.berlin.domain.exception.InvalidProjectException import com.berlin.domain.repository.ProjectRepository import com.berlin.domain.usecase.audit_system.AddAuditLogUseCase +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import data.UserCache import io.mockk.every @@ -20,17 +21,19 @@ class DeleteProjectUseCaseTest { private val projectRepository: ProjectRepository = mockk(relaxed = true) private val addAuditLogUseCase: AddAuditLogUseCase = mockk(relaxed = true) private val cashedUser: UserCache = mockk(relaxed = true) + private val validator: Validator = mockk(relaxed = true) @BeforeEach fun setup() { deleteProjectUseCase = DeleteProjectUseCase( - projectRepository, addAuditLogUseCase, cashedUser + projectRepository, addAuditLogUseCase, cashedUser,validator ) } @Test fun `should return Deleted Successfully when project deleted successfully`() { // Given + every { validator.isValid(any()) } returns true every { projectRepository.deleteProject(any()) } returns "Deleted Successfully" every { cashedUser.currentUser.id } returns "user_123" @@ -49,6 +52,7 @@ class DeleteProjectUseCaseTest { @Test fun `should return throw ProjectNotFoundException when project deletion fails`() { // Given + every { validator.isValid("P1") } returns true every { projectRepository.deleteProject("P1") } throws InvalidProjectException("") // When// Then @@ -62,6 +66,7 @@ class DeleteProjectUseCaseTest { @Test fun `should throw exception when project id does not exists`() { // Given + every { validator.isValid(any()) } returns true every { projectRepository.deleteProject(any()) } throws InvalidProjectException("") // When// Then diff --git a/src/test/kotlin/domain/usecase/project/GetProjectByIdUseCaseTest.kt b/src/test/kotlin/domain/usecase/project/GetProjectByIdUseCaseTest.kt index b9cc582..9928b21 100644 --- a/src/test/kotlin/domain/usecase/project/GetProjectByIdUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/project/GetProjectByIdUseCaseTest.kt @@ -2,6 +2,7 @@ package com.berlin.domain.usecase.project import com.berlin.domain.exception.ProjectNotFoundException import com.berlin.domain.repository.ProjectRepository +import com.berlin.domain.usecase.utils.validation.Validator import com.berlin.helper.projectHelper import com.google.common.truth.Truth.assertThat import io.mockk.every @@ -16,16 +17,18 @@ class GetProjectByIdUseCaseTest { private lateinit var getProjectByIdUseCase: GetProjectByIdUseCase private val projectRepository: ProjectRepository = mockk(relaxed = true) + private val validator: Validator = mockk(relaxed = true) @BeforeEach fun setup() { - getProjectByIdUseCase = GetProjectByIdUseCase(projectRepository) + getProjectByIdUseCase = GetProjectByIdUseCase(projectRepository,validator) } @Test fun `should return project when valid project id exists`() { // Given val expectedProject = projectHelper() + every { validator.isValid("P1") } returns true every { projectRepository.getProjectById("P1") } returns expectedProject // When @@ -38,6 +41,7 @@ class GetProjectByIdUseCaseTest { @Test fun `should throw exception when project id does not exist`() { // Given + every { validator.isValid(any()) } returns true every { projectRepository.getProjectById(any()) } throws ProjectNotFoundException("") // When // Then assertThrows { getProjectByIdUseCase("P2") } diff --git a/src/test/kotlin/domain/usecase/project/UpdateProjectUseCaseTest.kt b/src/test/kotlin/domain/usecase/project/UpdateProjectUseCaseTest.kt index 929ddbe..afe805f 100644 --- a/src/test/kotlin/domain/usecase/project/UpdateProjectUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/project/UpdateProjectUseCaseTest.kt @@ -3,6 +3,7 @@ package com.berlin.domain.usecase.project import com.berlin.domain.exception.InvalidProjectException import com.berlin.domain.repository.ProjectRepository import com.berlin.domain.usecase.audit_system.AddAuditLogUseCase +import com.berlin.domain.usecase.utils.validation.Validator import com.berlin.helper.projectHelper import com.google.common.truth.Truth.assertThat import data.UserCache @@ -21,11 +22,12 @@ class UpdateProjectUseCaseTest { private val projectRepository: ProjectRepository = mockk(relaxed = true) private val addAuditLogUseCase: AddAuditLogUseCase = mockk(relaxed = true) private val cashedUser: UserCache = mockk(relaxed = true) + private val validator: Validator = mockk(relaxed = true) @BeforeEach fun setup() { updateProjectUseCase = UpdateProjectUseCase( - projectRepository, addAuditLogUseCase, cashedUser + projectRepository, addAuditLogUseCase, cashedUser,validator ) } @@ -33,6 +35,7 @@ class UpdateProjectUseCaseTest { fun `should return Updated Successfully when project update succeeds`() { // Given val project = projectHelper() + every { validator.isValid(any()) }returns true every { projectRepository.updateProject(project) } returns "Updated Successfully" every { cashedUser.currentUser.id } returns "user_123" diff --git a/src/test/kotlin/domain/usecase/task/ChangeTaskStateUseCaseTest.kt b/src/test/kotlin/domain/usecase/task/ChangeTaskStateUseCaseTest.kt index 3b7655e..f1050a7 100644 --- a/src/test/kotlin/domain/usecase/task/ChangeTaskStateUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/task/ChangeTaskStateUseCaseTest.kt @@ -7,6 +7,7 @@ import com.berlin.domain.model.Task import com.berlin.domain.model.user.User import com.berlin.domain.repository.TaskRepository import com.berlin.domain.usecase.audit_system.AddAuditLogUseCase +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import data.UserCache import io.mockk.* @@ -20,6 +21,7 @@ class ChangeTaskStateUseCaseTest { private lateinit var addAuditLogUseCase: AddAuditLogUseCase private lateinit var userCache: UserCache private lateinit var changeTaskStateUseCase: ChangeTaskStateUseCase + private lateinit var validator: Validator private val creator = mockk(relaxed = true) @@ -38,6 +40,7 @@ class ChangeTaskStateUseCaseTest { taskRepository = mockk() addAuditLogUseCase = mockk(relaxUnitFun = true) userCache = mockk() + validator= mockk( relaxed = true) every { creator.id } returns "U1" every { userCache.currentUser } returns creator @@ -52,7 +55,7 @@ class ChangeTaskStateUseCaseTest { ) } just Runs - changeTaskStateUseCase = ChangeTaskStateUseCase(taskRepository, addAuditLogUseCase, userCache) + changeTaskStateUseCase = ChangeTaskStateUseCase(taskRepository, addAuditLogUseCase, userCache,validator) } private fun verifyAudit(taskId: String) { @@ -68,6 +71,7 @@ class ChangeTaskStateUseCaseTest { @Test fun `result is success when state changes`() { + every { validator.isValid(any()) }returns true every { taskRepository.getTaskById("1") } returns existingTask every { taskRepository.updateTask(any()) } answers { firstArg() } @@ -92,6 +96,7 @@ class ChangeTaskStateUseCaseTest { @Test fun `throws IllegalStateException when repository update fails`() { + every { validator.isValid(any()) }returns true every { taskRepository.getTaskById("1") } returns existingTask every { taskRepository.updateTask(any()) } throws IllegalStateException("boom") diff --git a/src/test/kotlin/domain/usecase/task/CreateTaskUseCaseTest.kt b/src/test/kotlin/domain/usecase/task/CreateTaskUseCaseTest.kt index 34f869f..8432ba6 100644 --- a/src/test/kotlin/domain/usecase/task/CreateTaskUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/task/CreateTaskUseCaseTest.kt @@ -7,6 +7,7 @@ import com.berlin.domain.model.Task import com.berlin.domain.repository.TaskRepository import com.berlin.domain.usecase.audit_system.AddAuditLogUseCase import com.berlin.domain.usecase.utils.id_generator.IdGenerator +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import io.mockk.* import org.junit.jupiter.api.BeforeEach @@ -21,6 +22,7 @@ class CreateTaskUseCaseTest { private lateinit var idGenerator: IdGenerator private lateinit var addAuditLogUseCase: AddAuditLogUseCase private lateinit var createTaskUseCase: CreateTaskUseCase + private lateinit var validator: Validator private val projectId = "P1" private val createByUserId = "U1" @@ -31,7 +33,8 @@ class CreateTaskUseCaseTest { taskRepository = mockk(relaxed = true) idGenerator = mockk(relaxed = true) addAuditLogUseCase = mockk(relaxUnitFun = true) - createTaskUseCase = CreateTaskUseCase(taskRepository, idGenerator, addAuditLogUseCase) + validator= mockk(relaxed = true) + createTaskUseCase = CreateTaskUseCase(taskRepository, idGenerator, addAuditLogUseCase,validator) } @Test @@ -48,7 +51,7 @@ class CreateTaskUseCaseTest { assignedToUserId = assignedToUserId, createByUserId = createByUserId ) - + every { validator.isValid(any()) }returns true every { idGenerator.generateId(trimmed, any(), any()) } returns generatedId every { taskRepository.getTaskById(generatedId) } returns newTask every { taskRepository.createTask(any()) } returns newTask @@ -86,6 +89,7 @@ class CreateTaskUseCaseTest { val trimmed = rawTitle.trim() val existingId = "T999" + every { validator.isValid(any()) }returns true every { idGenerator.generateId(trimmed, any(), any()) } returns existingId every { taskRepository.getTaskById(existingId) } throws NoSuchElementException() @@ -120,6 +124,7 @@ class CreateTaskUseCaseTest { val trimmed = rawTitle.trim() val generatedId = "T500" + every { validator.isValid(any()) }returns true every { idGenerator.generateId(trimmed, any(), any()) } returns generatedId every { taskRepository.getTaskById(generatedId) } returns Task( generatedId, projectId, trimmed, null, "TODO", assignedToUserId, createByUserId diff --git a/src/test/kotlin/domain/usecase/task/DeleteTaskUseCaseTest.kt b/src/test/kotlin/domain/usecase/task/DeleteTaskUseCaseTest.kt index af23f4e..65d12dc 100644 --- a/src/test/kotlin/domain/usecase/task/DeleteTaskUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/task/DeleteTaskUseCaseTest.kt @@ -4,6 +4,7 @@ import com.berlin.domain.model.AuditLog import com.berlin.domain.model.user.User import com.berlin.domain.repository.TaskRepository import com.berlin.domain.usecase.audit_system.AddAuditLogUseCase +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import data.UserCache import io.mockk.* @@ -17,6 +18,7 @@ class DeleteTaskUseCaseTest { private lateinit var addAuditLogUseCase: AddAuditLogUseCase private lateinit var userCache: UserCache private lateinit var deleteTaskUseCase: DeleteTaskUseCase + private lateinit var validator: Validator private lateinit var currentUser: User @@ -25,6 +27,7 @@ class DeleteTaskUseCaseTest { taskRepository = mockk() addAuditLogUseCase = mockk(relaxUnitFun = true) userCache = mockk() + validator= mockk() currentUser = mockk(relaxed = true) every { currentUser.id } returns "U1" @@ -39,11 +42,12 @@ class DeleteTaskUseCaseTest { ) } just Runs - deleteTaskUseCase = DeleteTaskUseCase(taskRepository, addAuditLogUseCase, userCache) + deleteTaskUseCase = DeleteTaskUseCase(taskRepository, addAuditLogUseCase, userCache,validator) } @Test fun `returns Deleted when repository deletes task`() { + every { validator.isValid("T1") }returns true every { taskRepository.deleteTask("T1") } just Runs val result = deleteTaskUseCase("T1") @@ -62,6 +66,7 @@ class DeleteTaskUseCaseTest { @Test fun `throws IllegalStateException when repository delete throws`() { + every { validator.isValid("T1") }returns true every { taskRepository.deleteTask("T1") } throws IllegalStateException("boom") assertThrows { diff --git a/src/test/kotlin/domain/usecase/task/GetTaskByIdUseCaseTest.kt b/src/test/kotlin/domain/usecase/task/GetTaskByIdUseCaseTest.kt index 615184e..514bd4b 100644 --- a/src/test/kotlin/domain/usecase/task/GetTaskByIdUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/task/GetTaskByIdUseCaseTest.kt @@ -3,6 +3,7 @@ package com.berlin.domain.usecase.task import com.berlin.domain.exception.InvalidTaskIdException import com.berlin.domain.model.Task import com.berlin.domain.repository.TaskRepository +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk @@ -15,6 +16,7 @@ class GetTaskByIdUseCaseTest { private lateinit var taskRepository: TaskRepository private lateinit var getTaskByIdUseCase: GetTaskByIdUseCase + private lateinit var validator: Validator private val validId = "T1" private val stored = Task( @@ -30,12 +32,14 @@ class GetTaskByIdUseCaseTest { @BeforeEach fun setUp() { taskRepository = mockk() - getTaskByIdUseCase = GetTaskByIdUseCase(taskRepository) + validator= mockk(relaxed = true) + getTaskByIdUseCase = GetTaskByIdUseCase(taskRepository,validator) } @Test fun `returns task when repository returns a task`() { // stub repo to return directly + every { validator.isValid(validId) }returns true every { taskRepository.getTaskById(validId) } returns stored val result = getTaskByIdUseCase(validId) @@ -46,6 +50,7 @@ class GetTaskByIdUseCaseTest { @Test fun `throws repository exception when repo fails`() { val ex = IllegalStateException("boom") + every { validator.isValid(validId) }returns true every { taskRepository.getTaskById(validId) } throws ex assertThrows { diff --git a/src/test/kotlin/domain/usecase/task/GetTasksByProjectUseCaseTest.kt b/src/test/kotlin/domain/usecase/task/GetTasksByProjectUseCaseTest.kt index 721a13d..eb9fe95 100644 --- a/src/test/kotlin/domain/usecase/task/GetTasksByProjectUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/task/GetTasksByProjectUseCaseTest.kt @@ -3,6 +3,7 @@ package com.berlin.domain.usecase.task import com.berlin.domain.exception.InvalidProjectIdException import com.berlin.domain.model.Task import com.berlin.domain.repository.TaskRepository +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk @@ -15,6 +16,7 @@ class GetTasksByProjectUseCaseTest { private lateinit var taskRepository: TaskRepository private lateinit var getTasksByProjectUseCase: GetTasksByProjectUseCase + private lateinit var validator: Validator private val task = Task( id = "1", @@ -29,11 +31,13 @@ class GetTasksByProjectUseCaseTest { @BeforeEach fun setUp() { taskRepository = mockk() - getTasksByProjectUseCase = GetTasksByProjectUseCase(taskRepository) + validator= mockk(relaxed = true) + getTasksByProjectUseCase = GetTasksByProjectUseCase(taskRepository,validator) } @Test fun `returns tasks when repository returns non-empty list`() { + every { validator.isValid("P1") }returns true every { taskRepository.getTasksByProjectId("P1") } returns listOf(task) val result = getTasksByProjectUseCase("P1") @@ -43,6 +47,7 @@ class GetTasksByProjectUseCaseTest { @Test fun `returns empty list when repository returns empty list`() { + every { validator.isValid("P1") }returns true every { taskRepository.getTasksByProjectId("P1") } returns emptyList() val result = getTasksByProjectUseCase("P1") @@ -52,6 +57,7 @@ class GetTasksByProjectUseCaseTest { @Test fun `throws IllegalStateException when repository throws`() { + every { validator.isValid("P1") }returns true every { taskRepository.getTasksByProjectId("P1") } throws IllegalStateException("boom") assertThrows { diff --git a/src/test/kotlin/domain/usecase/task_state/CreateTaskStateUseCaseTest.kt b/src/test/kotlin/domain/usecase/task_state/CreateTaskStateUseCaseTest.kt index ed9d4b1..8d94cf2 100644 --- a/src/test/kotlin/domain/usecase/task_state/CreateTaskStateUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/task_state/CreateTaskStateUseCaseTest.kt @@ -5,6 +5,7 @@ import com.berlin.domain.exception.InvalidStateNameException import com.berlin.domain.model.TaskState import com.berlin.domain.repository.TaskStateRepository import com.berlin.domain.usecase.utils.id_generator.IdGeneratorImplementation +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk @@ -18,13 +19,14 @@ class CreateTaskStateUseCaseTest { private lateinit var createTaskStateUseCase: CreateTaskStateUseCase private val taskStateRepository: TaskStateRepository = mockk(relaxed = true) + private val validator: Validator = mockk(relaxed = true) @BeforeEach fun setup() { val idGenerator: IdGeneratorImplementation = mockk(relaxed = true) createTaskStateUseCase = CreateTaskStateUseCase( taskStateRepository, - idGenerator + idGenerator,validator ) } @@ -32,6 +34,7 @@ class CreateTaskStateUseCaseTest { fun `createNewState should return success when state created successfully`() { // Given val validState = TaskState(id = "S1", name = "TODO", projectId = "P1") + every { validator.isValid(any()) }returns true every { taskStateRepository.addState(any()) } returns "State created successfully" every { taskStateRepository.getStateById(any()) } returns mockk() @@ -51,6 +54,7 @@ class CreateTaskStateUseCaseTest { fun `createNewState should throw exception when state creation fails`() { // Given val validState = TaskState(id = "S1", name = "S1", projectId = "1") + every { validator.isValid(any()) }returns true every { taskStateRepository.addState(any()) } throws InvalidStateException("can not add state") every { taskStateRepository.getStateById(any()) } returns mockk() diff --git a/src/test/kotlin/domain/usecase/task_state/DeleteTaskStateUseCaseTest.kt b/src/test/kotlin/domain/usecase/task_state/DeleteTaskStateUseCaseTest.kt index caf504d..bc20be7 100644 --- a/src/test/kotlin/domain/usecase/task_state/DeleteTaskStateUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/task_state/DeleteTaskStateUseCaseTest.kt @@ -3,6 +3,7 @@ package com.berlin.domain.usecase.task_state import com.berlin.domain.exception.InvalidStateException import com.berlin.domain.exception.InvalidStateIdException import com.berlin.domain.repository.TaskStateRepository +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk @@ -13,15 +14,17 @@ import kotlin.test.Test class DeleteTaskStateUseCaseTest { private lateinit var deleteTaskStateUseCase: DeleteTaskStateUseCase private val taskStateRepository: TaskStateRepository = mockk(relaxed = true) + private val validator: Validator = mockk(relaxed = true) @BeforeEach fun setup() { - deleteTaskStateUseCase = DeleteTaskStateUseCase(taskStateRepository) + deleteTaskStateUseCase = DeleteTaskStateUseCase(taskStateRepository,validator) } @Test fun `should return success when state is deleted successfully`() { // Given + every { validator.isValid(any()) }returns true every { taskStateRepository.deleteState(any()) } returns "Deleted Successfully" every { taskStateRepository.getStateById(any()) } returns mockk() @@ -35,6 +38,7 @@ class DeleteTaskStateUseCaseTest { @Test fun `should return failure when state deletion fails`() { // Given + every { validator.isValid(any()) }returns true every { taskStateRepository.deleteState(any()) } returns "Deletion Failed" every { taskStateRepository.getStateById(any()) } returns mockk() @@ -50,6 +54,7 @@ class DeleteTaskStateUseCaseTest { fun `should throw exception when state does not exist`() { // Given val stateId = "q2" + every { validator.isValid(any()) }returns true every { taskStateRepository.deleteState(any()) } throws InvalidStateException(stateId) // When & Then @@ -60,6 +65,7 @@ class DeleteTaskStateUseCaseTest { @Test fun `should throw InvalidStateException when state does not exist`() { val stateId = "q2" + every { validator.isValid(stateId) }returns true every { taskStateRepository.deleteState(stateId) } throws InvalidStateException(stateId) assertThrows { diff --git a/src/test/kotlin/domain/usecase/task_state/GetAllTaskStatesByProjectIdUseCaseTest.kt b/src/test/kotlin/domain/usecase/task_state/GetAllTaskStatesByProjectIdUseCaseTest.kt index fdcd453..eb28472 100644 --- a/src/test/kotlin/domain/usecase/task_state/GetAllTaskStatesByProjectIdUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/task_state/GetAllTaskStatesByProjectIdUseCaseTest.kt @@ -3,6 +3,7 @@ package com.berlin.domain.usecase.task_state import com.berlin.domain.model.TaskState import com.berlin.domain.repository.ProjectRepository import com.berlin.domain.repository.TaskStateRepository +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk @@ -17,12 +18,13 @@ class GetAllTaskStatesByProjectIdUseCaseTest { private lateinit var getAllTaskStatesByProjectIdUseCase: GetAllTaskStatesByProjectIdUseCase private val taskStateRepository: TaskStateRepository = mockk(relaxed = true) private val projectRepository: ProjectRepository = mockk(relaxed = true) + private val validator: Validator = mockk(relaxed = true) @BeforeEach fun setup() { getAllTaskStatesByProjectIdUseCase = GetAllTaskStatesByProjectIdUseCase( taskStateRepository, - projectRepository + projectRepository,validator ) } @@ -33,6 +35,7 @@ class GetAllTaskStatesByProjectIdUseCaseTest { TaskState(id = "S1", name = "Active", projectId = "P1"), TaskState(id = "S2", name = "Inactive", projectId = "P1") ) + every { validator.isValid("P1") }returns true every { projectRepository.getProjectById("P1") } returns mockk() every { taskStateRepository.getStatesByProjectId("P1") } returns expectedStates @@ -46,6 +49,7 @@ class GetAllTaskStatesByProjectIdUseCaseTest { @Test fun `should return empty when no states are found for the project`() { // Given + every { validator.isValid("P3") }returns true every { taskStateRepository.getStatesByProjectId("P3") } returns emptyList() // When val result = getAllTaskStatesByProjectIdUseCase("P3") diff --git a/src/test/kotlin/domain/usecase/task_state/GetTaskStateByIdUseCaseTest.kt b/src/test/kotlin/domain/usecase/task_state/GetTaskStateByIdUseCaseTest.kt index 07414dc..9b6f7ef 100644 --- a/src/test/kotlin/domain/usecase/task_state/GetTaskStateByIdUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/task_state/GetTaskStateByIdUseCaseTest.kt @@ -3,6 +3,7 @@ package com.berlin.domain.usecase.task_state import com.berlin.domain.exception.StateNotFoundException import com.berlin.domain.model.TaskState import com.berlin.domain.repository.TaskStateRepository +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk @@ -16,17 +17,19 @@ class GetTaskStateByIdUseCaseTest { private lateinit var getTaskStateByIdUseCase: GetTaskStateByIdUseCase private lateinit var taskStateRepository: TaskStateRepository + private val validator: Validator = mockk(relaxed = true) @BeforeEach fun setup() { taskStateRepository = mockk() - getTaskStateByIdUseCase = GetTaskStateByIdUseCase(taskStateRepository) + getTaskStateByIdUseCase = GetTaskStateByIdUseCase(taskStateRepository,validator) } @Test fun `should return state when valid state id exists`() { // Given val expectedState = TaskState(id = "S1", name = "Active", projectId = "P1") + every { validator.isValid("S1") }returns true every { taskStateRepository.getStateById("S1") } returns expectedState // When @@ -40,6 +43,7 @@ class GetTaskStateByIdUseCaseTest { fun `should throw exception when state id does not exist`() { // Given val input = "S2" + every { validator.isValid(any()) }returns true every { taskStateRepository.getStateById(any()) } throws StateNotFoundException(input) // When & Then diff --git a/src/test/kotlin/domain/usecase/task_state/GetTaskStateByTaskIdUseCaseTest.kt b/src/test/kotlin/domain/usecase/task_state/GetTaskStateByTaskIdUseCaseTest.kt index a126b11..7b740e7 100644 --- a/src/test/kotlin/domain/usecase/task_state/GetTaskStateByTaskIdUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/task_state/GetTaskStateByTaskIdUseCaseTest.kt @@ -3,6 +3,7 @@ package com.berlin.domain.usecase.task_state import com.berlin.domain.model.TaskState import com.berlin.domain.repository.TaskRepository import com.berlin.domain.repository.TaskStateRepository +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk @@ -17,16 +18,19 @@ class GetTaskStateByTaskIdUseCaseTest { private lateinit var getTaskStateByTaskIdUseCase: GetTaskStateByTaskIdUseCase private val taskStateRepository: TaskStateRepository = mockk(relaxed = true) private val taskRepository: TaskRepository = mockk(relaxed = true) + private val validator: Validator = mockk(relaxed = true) + @BeforeEach fun setup() { - getTaskStateByTaskIdUseCase = GetTaskStateByTaskIdUseCase(taskStateRepository, taskRepository) + getTaskStateByTaskIdUseCase = GetTaskStateByTaskIdUseCase(taskStateRepository, taskRepository,validator) } @Test fun `should return state when task id exists`() { // Given val expectedState = TaskState(id = "S1", name = "Active", projectId = "P1") + every { validator.isValid("T1") }returns true every { taskRepository.getTaskById("T1") } returns mockk() every { taskStateRepository.getStateByTaskId("T1") } returns expectedState diff --git a/src/test/kotlin/domain/usecase/task_state/GetTasksByTaskStateIdUseCaseTest.kt b/src/test/kotlin/domain/usecase/task_state/GetTasksByTaskStateIdUseCaseTest.kt index 9523ec6..b1c66f7 100644 --- a/src/test/kotlin/domain/usecase/task_state/GetTasksByTaskStateIdUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/task_state/GetTasksByTaskStateIdUseCaseTest.kt @@ -2,6 +2,7 @@ package com.berlin.domain.usecase.task_state import com.berlin.domain.model.Task import com.berlin.domain.repository.TaskStateRepository +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk @@ -15,6 +16,7 @@ class GetTasksByTaskStateIdUseCaseTest { private lateinit var getTasksByTaskStateIdUseCase: GetTasksByTaskStateIdUseCase private val taskStateRepository: TaskStateRepository = mockk(relaxed = true) + private val validator: Validator = mockk(relaxed = true) private val task = Task( id = "T1", @@ -28,13 +30,14 @@ class GetTasksByTaskStateIdUseCaseTest { @BeforeEach fun setup() { - getTasksByTaskStateIdUseCase = GetTasksByTaskStateIdUseCase(taskStateRepository) + getTasksByTaskStateIdUseCase = GetTasksByTaskStateIdUseCase(taskStateRepository,validator) } @Test fun `should return tasks when tasks are found for the state`() { // Given val expectedTasks = listOf(task) + every { validator.isValid("S1") }returns true every { taskStateRepository.getTasksByStateId("S1") } returns expectedTasks every { taskStateRepository.getStateById("S1") } returns mockk() @@ -48,6 +51,7 @@ class GetTasksByTaskStateIdUseCaseTest { @Test fun `should throw exception when no tasks are found for the state`() { // Given + every { validator.isValid("S2") }returns true every { taskStateRepository.getTasksByStateId("S2") } returns null every { taskStateRepository.getStateById("S2") } returns mockk() diff --git a/src/test/kotlin/domain/usecase/task_state/UpdateTaskStateUseCaseTest.kt b/src/test/kotlin/domain/usecase/task_state/UpdateTaskStateUseCaseTest.kt index e1d370d..4123c7e 100644 --- a/src/test/kotlin/domain/usecase/task_state/UpdateTaskStateUseCaseTest.kt +++ b/src/test/kotlin/domain/usecase/task_state/UpdateTaskStateUseCaseTest.kt @@ -2,6 +2,7 @@ package com.berlin.domain.usecase.task_state import com.berlin.domain.model.TaskState import com.berlin.domain.repository.TaskStateRepository +import com.berlin.domain.usecase.utils.validation.Validator import com.google.common.truth.Truth.assertThat import io.mockk.every import io.mockk.mockk @@ -15,16 +16,18 @@ class UpdateTaskStateUseCaseTest { private lateinit var updateTaskStateUseCase: UpdateTaskStateUseCase private val taskStateRepository: TaskStateRepository = mockk(relaxed = true) + private val validator: Validator = mockk(relaxed = true) @BeforeEach fun setup() { - updateTaskStateUseCase = UpdateTaskStateUseCase(taskStateRepository) + updateTaskStateUseCase = UpdateTaskStateUseCase(taskStateRepository,validator) } @Test fun `should return success when state update succeeds`() { // Given val state = TaskState(id = "S1", name = "Active", projectId = "P1") + every { validator.isValid(any()) }returns true every { taskStateRepository.updateState(state) } returns "Updated Successfully" // When @@ -38,6 +41,7 @@ class UpdateTaskStateUseCaseTest { fun `should return exception when state update fails`() { // Given val state = TaskState(id = "S2", name = "Inactive", projectId = "P2") + every { validator.isValid(any()) }returns true every { taskStateRepository.updateState(state) } throws Exception() // When & Then From 84a8804a0ac29471e1605c319ae04a0eddebb216 Mon Sep 17 00:00:00 2001 From: Noha Saad Date: Thu, 15 May 2025 19:58:38 +0300 Subject: [PATCH 6/6] merge conflict --- src/main/kotlin/di/useCaseModule.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/di/useCaseModule.kt b/src/main/kotlin/di/useCaseModule.kt index 2a27414..5395805 100644 --- a/src/main/kotlin/di/useCaseModule.kt +++ b/src/main/kotlin/di/useCaseModule.kt @@ -20,13 +20,14 @@ import com.berlin.domain.usecase.task_state.GetTasksByTaskStateIdUseCase import com.berlin.domain.usecase.task_state.UpdateTaskStateUseCase import com.berlin.domain.usecase.utils.validation.NonBlankNonNumericValidator import com.berlin.domain.usecase.utils.validation.Validator -import data.UserCache import domain.usecase.auth_service.LoginUserUseCase import org.koin.core.module.dsl.singleOf +import org.koin.dsl.bind import org.koin.dsl.module val useCaseModule = module { - single { NonBlankNonNumericValidator() } + singleOf(::NonBlankNonNumericValidator) bind Validator::class + singleOf(::CreateTaskUseCase) singleOf(::AssignTaskUseCase) singleOf(::DeleteTaskUseCase)