diff --git a/build.gradle.kts b/build.gradle.kts index bc90217..9d1d4d6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ repositories { dependencies { implementation("io.insert-koin:koin-core:4.0.4") implementation ("org.jetbrains.kotlinx:kotlinx-datetime:0.6.2") - + implementation("com.opencsv:opencsv:5.7.1") testImplementation(kotlin("test")) testImplementation("org.junit.jupiter:junit-jupiter:5.8.1") testImplementation("io.mockk:mockk:1.14.0") diff --git a/src/main/kotlin/data/BaseDataSource.kt b/src/main/kotlin/data/BaseDataSource.kt new file mode 100644 index 0000000..8ec4838 --- /dev/null +++ b/src/main/kotlin/data/BaseDataSource.kt @@ -0,0 +1,17 @@ +package com.berlin.data + +interface BaseDataSource { + + fun getAll(): List + + fun getById(id: String): T? + + fun update(id: String, entity: T): Boolean + + fun delete(id: String): Boolean + + fun write(entity: T): Boolean + + fun writeAll(entities: List): Boolean + +} \ No newline at end of file diff --git a/src/main/kotlin/data/BaseSchema.kt b/src/main/kotlin/data/BaseSchema.kt new file mode 100644 index 0000000..eeddaf3 --- /dev/null +++ b/src/main/kotlin/data/BaseSchema.kt @@ -0,0 +1,10 @@ +package com.berlin.data + +interface BaseSchema { + val fileName: String + val header: List + + fun toRow(entity: T): List + fun fromRow(row: List): T? + fun getId(entity: T): String? +} \ No newline at end of file diff --git a/src/main/kotlin/data/indexes.kt b/src/main/kotlin/data/indexes.kt new file mode 100644 index 0000000..10630a5 --- /dev/null +++ b/src/main/kotlin/data/indexes.kt @@ -0,0 +1,42 @@ +package com.berlin.data + +object UserIndex { + const val ID = 0 + const val USER_NAME = 1 + const val PASSWORD = 2 + const val ROLE = 3 +} + +object TaskIndex { + const val ID = 0 + const val PROJECT_ID = 1 + const val TITLE = 2 + const val DESCRIPTION = 3 + const val STATE_ID = 4 + const val ASSIGNED_TO_USER_ID = 5 + const val CREATE_BY_USER_ID = 6 +} + +object StateIndex { + const val ID = 0 + const val NAME = 1 + const val PROJECT_ID = 2 +} + +object ProjectIndex { + const val ID = 0 + const val NAME = 1 + const val DESCRIPTION = 2 + const val STATES_ID = 3 + const val TASKS_ID = 4 +} + +object AuditLogIndex { + const val ID = 0 + const val TIMES_TAMP = 1 + const val CREATE_BY = 2 + const val AUDIT_ACTION = 3 + const val CHANGES_DESCRIPTION = 4 + const val ENTITY_TYPE = 5 + const val ENTITY_ID = 6 +} \ No newline at end of file diff --git a/src/main/kotlin/data/schema/AuditSchema.kt b/src/main/kotlin/data/schema/AuditSchema.kt new file mode 100644 index 0000000..9f5c751 --- /dev/null +++ b/src/main/kotlin/data/schema/AuditSchema.kt @@ -0,0 +1,96 @@ +package com.berlin.data.schema + +import com.berlin.data.AuditLogIndex +import com.berlin.data.BaseSchema +import com.berlin.domain.model.AuditAction +import com.berlin.domain.model.AuditLog +import com.berlin.domain.model.EntityType + +class AuditSchema( + override val fileName: String, override val header: List +) : BaseSchema { + + init { + require( + fileName.isNotEmpty() && header.size == NUMBER_OF_ATTRIBUTES + ) + } + + override fun toRow(entity: AuditLog): List { + return if (checkAuditLogIsNotValid(entity)) emptyList() + else auditLogToStringsList(entity) + } + + override fun fromRow(row: List): AuditLog? { + return if (checkRowIsNotValidAuditLog(row)) null + else stringsListToAuditLog(row) + } + + override fun getId(entity: AuditLog): String? { + return entity.id.ifEmpty { null } + } + + private fun auditLogToStringsList(auditLog: AuditLog): List { + return listOf( + auditLog.id, + auditLog.timestamp.toString(), + auditLog.createdByUserId, + auditLog.auditAction.toString(), + auditLog.changesDescription ?: "", + auditLog.entityType.toString(), + auditLog.entityId + ) + } + + private fun stringsListToAuditLog(row: List): AuditLog { + return AuditLog( + id = row[AuditLogIndex.ID], + timestamp = row[AuditLogIndex.TIMES_TAMP].toLong() , + createdByUserId = row[AuditLogIndex.CREATE_BY], + auditAction = stringToAuditAction(row[AuditLogIndex.AUDIT_ACTION]), + changesDescription = row[AuditLogIndex.CHANGES_DESCRIPTION].ifEmpty { null }, + entityType = stringToEntityType(row[AuditLogIndex.ENTITY_TYPE]), + entityId = row[AuditLogIndex.ENTITY_ID] + ) + } + + private fun checkRowIsNotValidAuditLog(row: List): Boolean { + return (row[AuditLogIndex.ID].isEmpty() || + row[AuditLogIndex.TIMES_TAMP].isEmpty() || + row[AuditLogIndex.CREATE_BY].isEmpty() || + row[AuditLogIndex.AUDIT_ACTION].isEmpty() || + row[AuditLogIndex.ENTITY_ID].isEmpty() || + row[AuditLogIndex.AUDIT_ACTION] !in enumValues().map { it.name } || + row[AuditLogIndex.ENTITY_TYPE] !in enumValues().map { it.name } + ) + } + + private fun stringToAuditAction(auditAction: String): AuditAction { + return when (auditAction) { + AuditAction.CREATE.toString() -> AuditAction.CREATE + AuditAction.UPDATE.toString() -> AuditAction.UPDATE + AuditAction.DELETE.toString() -> AuditAction.DELETE + else -> AuditAction.CREATE + } + } + + private fun stringToEntityType(entityType: String): EntityType { + return when (entityType) { + EntityType.TASK.toString() -> EntityType.TASK + EntityType.PROJECT.toString() -> EntityType.PROJECT + else -> EntityType.TASK + } + } + + private fun checkAuditLogIsNotValid(auditLog: AuditLog): Boolean { + return (auditLog.id.isEmpty() || + auditLog.timestamp <= 0 || + auditLog.createdByUserId.isEmpty() || + auditLog.entityId.isEmpty() + ) + } + + private companion object { + const val NUMBER_OF_ATTRIBUTES = 7 + } +} \ No newline at end of file diff --git a/src/main/kotlin/data/schema/ProjectSchema.kt b/src/main/kotlin/data/schema/ProjectSchema.kt new file mode 100644 index 0000000..7004980 --- /dev/null +++ b/src/main/kotlin/data/schema/ProjectSchema.kt @@ -0,0 +1,70 @@ +package com.berlin.data.schema + +import com.berlin.data.BaseSchema +import com.berlin.data.ProjectIndex +import com.berlin.domain.model.Project + +class ProjectSchema( + override val fileName: String, + override val header: List +) : BaseSchema { + + init { + require(fileName.isNotEmpty() && header.size == NUMBER_OF_ATTRIBUTES) + } + + override fun toRow(entity: Project): List { + return if (checkProjectIsNotValid(entity)) emptyList() + else projectToStringsList(entity) + } + + override fun fromRow(row: List): Project? { + return if (checkRowIsNotValidProject(row)) null + else stringsListToProject(row) + } + + override fun getId(entity: Project): String? { + return entity.id.ifEmpty { null } + } + + private fun projectToStringsList(project: Project): List { + return listOf( + project.id, + project.name, + project.description ?: "", + project.statesId?.joinToString(",", "[", "]") ?: "[]", + project.tasksId?.joinToString(",", "[", "]") ?: "[]" + ) + } + + private fun stringsListToProject(row: List): Project { + return Project( + id = row[ProjectIndex.ID], + name = row[ProjectIndex.NAME], + description = row[ProjectIndex.DESCRIPTION].ifEmpty { null }, + statesId = row[ProjectIndex.STATES_ID].let { if (it == "[]") null else stringListToList(it) }, + tasksId = row[ProjectIndex.TASKS_ID].let { if (it == "[]") null else stringListToList(it) } + ) + } + + private fun checkRowIsNotValidProject(row: List): Boolean { + return (row.isEmpty()|| + row[ProjectIndex.ID].isEmpty() || + row[ProjectIndex.NAME].isEmpty()) + } + + private fun checkProjectIsNotValid(project: Project): Boolean { + return project.id.isEmpty() || + project.name.isEmpty() + } + + private fun stringListToList(listString: String): List { + return listString + .removeSurrounding("[", "]") + .split(",") + } + + private companion object { + const val NUMBER_OF_ATTRIBUTES = 5 + } +} \ No newline at end of file diff --git a/src/main/kotlin/data/schema/StateSchema.kt b/src/main/kotlin/data/schema/StateSchema.kt new file mode 100644 index 0000000..6a16ae0 --- /dev/null +++ b/src/main/kotlin/data/schema/StateSchema.kt @@ -0,0 +1,61 @@ +package com.berlin.data.schema + +import com.berlin.data.BaseSchema +import com.berlin.data.StateIndex +import com.berlin.domain.model.State + +class StateSchema( + override val fileName: String, + override val header: List +) : BaseSchema { + + init { + require(fileName.isNotEmpty() && header.size == NUMBER_OF_ATTRIBUTES) + } + + override fun toRow(entity: State): List { + return if (checkStateIsNotValid(entity)) emptyList() + else stateToStringsList(entity) + } + + override fun fromRow(row: List): State? { + return if (checkRowIsNotValidState(row)) null + else stringsListToState(row) + } + + override fun getId(entity: State): String? { + return entity.id.ifEmpty { null } + } + + private fun stateToStringsList(state: State): List { + return listOf( + state.id, + state.name, + state.projectId + ) + } + + private fun stringsListToState(row: List): State { + return State( + id = row[StateIndex.ID], + name = row[StateIndex.NAME], + projectId = row[StateIndex.PROJECT_ID] + ) + } + + private fun checkRowIsNotValidState(row: List): Boolean { + return (row[StateIndex.ID].isEmpty() || + row[StateIndex.NAME].isEmpty() || + row[StateIndex.PROJECT_ID].isEmpty()) + } + + private fun checkStateIsNotValid(state: State): Boolean { + return (state.id.isEmpty() || + state.name.isEmpty() || + state.projectId.isEmpty()) + } + + private companion object { + const val NUMBER_OF_ATTRIBUTES = 3 + } +} \ No newline at end of file diff --git a/src/main/kotlin/data/schema/TaskSchema.kt b/src/main/kotlin/data/schema/TaskSchema.kt new file mode 100644 index 0000000..5620f7a --- /dev/null +++ b/src/main/kotlin/data/schema/TaskSchema.kt @@ -0,0 +1,75 @@ +package com.berlin.data.schema + +import com.berlin.data.BaseSchema +import com.berlin.data.TaskIndex +import com.berlin.domain.model.Task + +class TaskSchema( + override val fileName: String, + override val header: List +) : BaseSchema { + + init { + require(fileName.isNotEmpty() && header.size == NUMBER_OF_ATTRIBUTES) + } + + override fun toRow(entity: Task): List { + return if (checkTaskIsNotValid(entity)) emptyList() + else taskToStringsList(entity) + } + + override fun fromRow(row: List): Task? { + return if (checkRowIsNotValidTask(row)) null + else stringsListToTask(row) + } + + override fun getId(entity: Task): String? { + return entity.id.ifEmpty { null } + } + + private fun taskToStringsList(task: Task): List { + return listOf( + task.id, + task.projectId, + task.title, + task.description ?: "", + task.stateId, + task.assignedToUserId, + task.createByUserId + ) + } + + private fun stringsListToTask(row: List): Task { + return Task( + id = row[TaskIndex.ID], + projectId = row[TaskIndex.PROJECT_ID], + title = row[TaskIndex.TITLE], + description = row[TaskIndex.DESCRIPTION].ifEmpty { null }, + stateId = row[TaskIndex.STATE_ID], + assignedToUserId = row[TaskIndex.ASSIGNED_TO_USER_ID], + createByUserId = row[TaskIndex.CREATE_BY_USER_ID] + ) + } + + private fun checkRowIsNotValidTask(row: List): Boolean { + return (row[TaskIndex.ID].isEmpty() || + row[TaskIndex.PROJECT_ID].isEmpty() || + row[TaskIndex.TITLE].isEmpty() || + row[TaskIndex.STATE_ID].isEmpty() || + row[TaskIndex.ASSIGNED_TO_USER_ID].isEmpty() || + row[TaskIndex.CREATE_BY_USER_ID].isEmpty()) + } + + private fun checkTaskIsNotValid(task: Task): Boolean { + return (task.id.isEmpty() || + task.projectId.isEmpty() || + task.title.isEmpty() || + task.stateId.isEmpty() || + task.assignedToUserId.isEmpty() || + task.createByUserId.isEmpty()) + } + + private companion object { + const val NUMBER_OF_ATTRIBUTES = 7 + } +} \ No newline at end of file diff --git a/src/main/kotlin/data/schema/UserSchema.kt b/src/main/kotlin/data/schema/UserSchema.kt new file mode 100644 index 0000000..e7a5959 --- /dev/null +++ b/src/main/kotlin/data/schema/UserSchema.kt @@ -0,0 +1,73 @@ +package com.berlin.data.schema + +import com.berlin.data.BaseSchema +import com.berlin.data.UserIndex +import com.berlin.domain.model.User +import com.berlin.domain.model.UserRole + +class UserSchema( + override val fileName: String, + override val header: List +) : BaseSchema { + + init { + require(fileName.isNotEmpty()&&header.size==NUMBER_OF_ATTRIBUTES) + } + + override fun toRow(entity: User): List { + return if (checkUserIsNotValid(entity)) emptyList() + else userToStringsList(entity) + } + + override fun fromRow(row: List): User? { + return if (checkRowIsNotValidUser(row)) null + else stringsListToUser(row) + } + + override fun getId(entity: User): String? { + return entity.id.ifEmpty { null } + } + + private fun userToStringsList(user: User): List { + return listOf( + user.id, + user.userName, + user.password, + user.role.toString() + ) + } + + private fun stringsListToUser(row: List): User { + return User( + id = row[UserIndex.ID], + userName = row[UserIndex.USER_NAME], + password = row[UserIndex.PASSWORD], + role = stringToUserRole(row[UserIndex.ROLE]) + ) + } + + private fun checkRowIsNotValidUser(row: List): Boolean { + return (row[UserIndex.ID].isEmpty() || + row[UserIndex.USER_NAME].isEmpty() || + row[UserIndex.PASSWORD].isEmpty() || + row[UserIndex.ROLE] !in enumValues().map { it.name }) + } + + private fun checkUserIsNotValid(user: User): Boolean { + return (user.id.isEmpty() || + user.userName.isEmpty() || + user.password.isEmpty()) + } + + private fun stringToUserRole(roleString: String): UserRole { + return when (roleString) { + UserRole.ADMIN.toString() -> UserRole.ADMIN + UserRole.MATE.toString() -> UserRole.MATE + else -> UserRole.MATE + } + } + + private companion object { + const val NUMBER_OF_ATTRIBUTES = 4 + } +} \ No newline at end of file diff --git a/src/test/kotlin/data/schema/AuditSchemaTest.kt b/src/test/kotlin/data/schema/AuditSchemaTest.kt new file mode 100644 index 0000000..ef3c8b4 --- /dev/null +++ b/src/test/kotlin/data/schema/AuditSchemaTest.kt @@ -0,0 +1,366 @@ +package data.schema + +import com.berlin.data.schema.AuditSchema +import com.berlin.domain.model.AuditAction +import com.berlin.domain.model.AuditLog +import com.berlin.domain.model.EntityType +import com.google.common.truth.Truth.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +class AuditSchemaTest { + + private lateinit var auditSchema: AuditSchema + + @BeforeEach + fun setup() { + auditSchema = fakeAuditSchema() + } + + //region create object + + @Test + fun `should throw IllegalArgumentException when try to create object with blank file name`() { + //when //then + assertThrows { + auditSchema = AuditSchema("", listOf("a", "b", "c", "d", "e", "f", "g")) + } + } + + @Test + fun `should throw IllegalArgumentException when try to create object with invalid size header`() { + //when //then + assertThrows { + auditSchema = AuditSchema("test.csv", listOf("a", "b")) + } + } + + //endregion + + //region toRow + + @Test + fun `toRow should return list of valid audit log attributes when valid audit log passed`() { + //when + val result = auditSchema.toRow(validAuditLog) + //then + assertThat(result).isEqualTo(validRow) + } + + @Test + fun `toRow should return list of valid audit log attributes when audit log with empty changesDescription passed`() { + //when + val result = auditSchema.toRow(validAuditLogEmptyChangesDescription) + //then + assertThat(result).isEqualTo(validRowEmptyChangesDescription) + } + + @Test + fun `toRow should return empty list when invalid audit log passed miss id attribute`() { + //when + val result = auditSchema.toRow(invalidAuditLogEmptyId) + //then + assertThat(result).isEmpty() + } + + @Test + fun `toRow should return empty list when invalid audit log passed miss timestamp attribute`() { + //when + val result = auditSchema.toRow(invalidAuditLogZeroTimestamp) + //then + assertThat(result).isEmpty() + } + + @Test + fun `toRow should return empty list when invalid audit log passed miss createdBy attribute`() { + //when + val result = auditSchema.toRow(invalidAuditLogEmptyCreatedBy) + //then + assertThat(result).isEmpty() + } + + @Test + fun `toRow should return empty list when invalid audit log passed miss entityId attribute`() { + //when + val result = auditSchema.toRow(invalidAuditLogEmptyEntityId) + //then + assertThat(result).isEmpty() + } + + //endregion + + //region fromRow + + @Test + fun `fromRow should return audit log when valid row task full passed`() { + //when + val result = auditSchema.fromRow(validRow) + //then + assertThat(result).isEqualTo(validAuditLog) + } + + @Test + fun `fromRow should return audit log when valid row project full passed`() { + //when + val result = auditSchema.fromRow(validRowProject) + //then + assertThat(result).isEqualTo(validAuditLogProject) + } + + @Test + fun `fromRow should return audit log when valid row empty changesDescription passed`() { + //when + val result = auditSchema.fromRow(validRowEmptyChangesDescription) + //then + assertThat(result).isEqualTo(validAuditLogEmptyChangesDescription) + } + + @Test + fun `fromRow should return null when invalid row passed miss id column`() { + //when + val result = auditSchema.fromRow(invalidRowEmptyId) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid row passed miss timestamp column`() { + //when + val result = auditSchema.fromRow(invalidRowEmptyTimestamp) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid row passed miss createdBy column`() { + //when + val result = auditSchema.fromRow(invalidRowEmptyCreatedBy) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid row passed miss auditAction column`() { + //when + val result = auditSchema.fromRow(invalidRowEmptyAuditAction) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid row passed wrong auditAction column`() { + //when + val result = auditSchema.fromRow(invalidRowWrongAuditAction) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid row passed miss entityType column`() { + //when + val result = auditSchema.fromRow(invalidRowEmptyEntityType) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid row passed miss entityId column`() { + //when + val result = auditSchema.fromRow(invalidRowEmptyEntityId) + //then + assertThat(result).isNull() + } + + //endregion + + //region getId + + @Test + fun `getId should return id of audit log passed`() { + //when + val result = auditSchema.getId(validAuditLog) + //then + assertThat(result).isEqualTo(validAuditLog.id) + } + + @Test + fun `getId should return null when audit log passed have empty id`() { + //when + val result = auditSchema.getId(invalidAuditLogEmptyId) + //then + assertThat(result).isNull() + } + + //endregion + + private fun fakeAuditSchema() = AuditSchema("test.csv", listOf("a", "b", "c", "d", "e", "f", "g")) + + private companion object { + + val testUserId = "u1" + + //region Some AuditLogs + + val validAuditLog = AuditLog( + id = "a1", + timestamp = 1000L, + createdByUserId = testUserId, + auditAction = AuditAction.CREATE, + changesDescription = "create", + entityType = EntityType.TASK, + entityId = "e1" + ) + val validAuditLogProject = AuditLog( + id = "a1", + timestamp = 1000L, + createdByUserId = testUserId, + auditAction = AuditAction.DELETE, + changesDescription = "create", + entityType = EntityType.PROJECT, + entityId = "e1" + ) + val validAuditLogEmptyChangesDescription = AuditLog( + id = "a1", + timestamp = 1000L, + createdByUserId = testUserId, + auditAction = AuditAction.CREATE, + changesDescription = null, + entityType = EntityType.TASK, + entityId = "e1" + ) + val invalidAuditLogEmptyId = AuditLog( + id = "", + timestamp = 1000L, + createdByUserId = testUserId, + auditAction = AuditAction.CREATE, + changesDescription = "create", + entityType = EntityType.TASK, + entityId = "e1" + ) + val invalidAuditLogZeroTimestamp = AuditLog( + id = "a1", + timestamp = 0L, + createdByUserId = testUserId, + auditAction = AuditAction.CREATE, + changesDescription = "create", + entityType = EntityType.TASK, + entityId = "e1" + ) + val invalidAuditLogEmptyCreatedBy = AuditLog( + id = "a1", + timestamp = 1000L, + createdByUserId = "", + auditAction = AuditAction.CREATE, + changesDescription = "create", + entityType = EntityType.TASK, + entityId = "e1" + ) + val invalidAuditLogEmptyEntityId = AuditLog( + id = "a1", + timestamp = 1000L, + createdByUserId = testUserId, + auditAction = AuditAction.CREATE, + changesDescription = "create", + entityType = EntityType.TASK, + entityId = "" + ) + + //endregion + + //region Some Rows + + val validRow = listOf( + "a1", + "1000", + "u1", + "CREATE", + "create", + "TASK", + "e1" + ) + val validRowProject = listOf( + "a1", + "1000", + "u1", + "DELETE", + "create", + "PROJECT", + "e1" + ) + val validRowEmptyChangesDescription = listOf( + "a1", + "1000", + "u1", + "CREATE", + "", + "TASK", + "e1" + ) + val invalidRowEmptyId = listOf( + "", + "1000", + "u1", + "CREATE", + "create", + "TASK", + "e1" + ) + val invalidRowEmptyTimestamp = listOf( + "a1", + "", + "u1", + "CREATE", + "create", + "TASK", + "e1" + ) + val invalidRowEmptyCreatedBy = listOf( + "a1", + "1000", + "", + "CREATE", + "create", + "TASK", + "e1" + ) + val invalidRowEmptyAuditAction = listOf( + "a1", + "1000", + "u1", + "", + "create", + "TASK", + "e1" + ) + val invalidRowWrongAuditAction = listOf( + "a1", + "1000", + "u1", + "jgj444h", + "create", + "TASK", + "e1" + ) + val invalidRowEmptyEntityType = listOf( + "a1", + "1000", + "u1", + "CREATE", + "create", + "", + "e1" + ) + val invalidRowEmptyEntityId = listOf( + "a1", + "1000", + "u1", + "CREATE", + "create", + "TASK", + "" + ) + + //endregion + } +} \ No newline at end of file diff --git a/src/test/kotlin/data/schema/ProjectSchemaTest.kt b/src/test/kotlin/data/schema/ProjectSchemaTest.kt new file mode 100644 index 0000000..c47e677 --- /dev/null +++ b/src/test/kotlin/data/schema/ProjectSchemaTest.kt @@ -0,0 +1,268 @@ +package data.schema + +import com.berlin.data.schema.ProjectSchema +import com.berlin.domain.model.Project +import com.google.common.truth.Truth.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +class ProjectSchemaTest { + + private lateinit var projectSchema: ProjectSchema + + @BeforeEach + fun setup() { + projectSchema = fakeProjectSchema() + } + + //region create object + + @Test + fun `should throw IllegalArgumentException when try to create object with blank file name`() { + //when //then + assertThrows { + projectSchema = ProjectSchema("", listOf("a", "b", "c", "d", "e")) + } + } + + @Test + fun `should throw IllegalArgumentException when try to create object with invalid size header`() { + //when //then + assertThrows { + projectSchema = ProjectSchema("test.csv", listOf("a", "b")) + } + } + + //endregion + + //region toRow + + @Test + fun `toRow should return list of valid project attributes when valid project passed`() { + //when + val result = projectSchema.toRow(validProject) + //then + assertThat(result).isEqualTo(validRow) + } + + @Test + fun `toRow should return list of valid project attributes when project with empty statesId passed`() { + //when + val result = projectSchema.toRow(validProjectEmptyStatesId) + //then + assertThat(result).isEqualTo(validRowEmptyStatesId) + } + + @Test + fun `toRow should return list of valid project attributes when project with empty description passed`() { + //when + val result = projectSchema.toRow(validProjectEmptyDescription) + //then + assertThat(result).isEqualTo(validRowEmptyDescription) + } + + @Test + fun `toRow should return list of valid project attributes when project with empty tasksId passed`() { + //when + val result = projectSchema.toRow(validProjectEmptyTasksId) + //then + assertThat(result).isEqualTo(validRowEmptyTasksId) + } + + @Test + fun `toRow should return empty list when invalid project passed miss id attribute`() { + //when + val result = projectSchema.toRow(invalidProjectEmptyId) + //then + assertThat(result).isEmpty() + } + + @Test + fun `toRow should return empty list when invalid project passed miss name attribute`() { + //when + val result = projectSchema.toRow(invalidProjectEmptyName) + //then + assertThat(result).isEmpty() + } + + //endregion + + //region fromRow + + @Test + fun `fromRow should return project when valid row full passed`() { + //when + val result = projectSchema.fromRow(validRow) + //then + assertThat(result).isEqualTo(validProject) + } + + @Test + fun `fromRow should return project when valid row empty description passed`() { + //when + val result = projectSchema.fromRow(validRowEmptyDescription) + //then + assertThat(result).isEqualTo(validProjectEmptyDescription) + } + + @Test + fun `fromRow should return project when valid row empty statesId passed`() { + //when + val result = projectSchema.fromRow(validRowEmptyStatesId) + //then + assertThat(result).isEqualTo(validProjectEmptyStatesId) + } + + @Test + fun `fromRow should return project when valid row empty tasksId passed`() { + //when + val result = projectSchema.fromRow(validRowEmptyTasksId) + //then + assertThat(result).isEqualTo(validProjectEmptyTasksId) + } + + @Test + fun `fromRow should return null when invalid row passed miss id column`() { + //when + val result = projectSchema.fromRow(invalidRowEmptyId) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when empty row passed miss id column`() { + //when + val result = projectSchema.fromRow(emptyList()) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid project passed miss name column`() { + //when + val result = projectSchema.fromRow(invalidRowEmptyName) + //then + assertThat(result).isNull() + } + + //endregion + + //region getId + + @Test + fun `getId should return id of project passed`() { + //when + val result = projectSchema.getId(validProject) + //then + assertThat(result).isEqualTo(validProject.id) + } + + @Test + fun `getId should return null when project passed have empty id`() { + //when + val result = projectSchema.getId(invalidProjectEmptyId) + //then + assertThat(result).isNull() + } + + //endregion + + private fun fakeProjectSchema() = ProjectSchema("test.csv", listOf("a", "b", "c", "d", "e")) + + private companion object { + //region Some Projects + + val validProject = Project( + id = "proj123", + name = "SampleProject", + description = "A sample project", + statesId = listOf("state1", "state2"), + tasksId = listOf("task1", "task2") + ) + val validProjectEmptyDescription = Project( + id = "proj123", + name = "SampleProject", + description = null, + statesId = listOf("state1", "state2"), + tasksId = listOf("task1", "task2") + ) + val validProjectEmptyStatesId = Project( + id = "proj123", + name = "SampleProject", + description = "A sample project", + statesId = null, + tasksId = listOf("task1", "task2") + ) + val validProjectEmptyTasksId = Project( + id = "proj123", + name = "SampleProject", + description = "A sample project", + statesId = listOf("state1", "state2"), + tasksId = null + ) + val invalidProjectEmptyId = Project( + id = "", + name = "SampleProject", + description = "A sample project", + statesId = listOf("state1", "state2"), + tasksId = listOf("task1", "task2") + ) + val invalidProjectEmptyName = Project( + id = "proj123", + name = "", + description = "A sample project", + statesId = listOf("state1", "state2"), + tasksId = listOf("task1", "task2") + ) + + //endregion + + //region Some Rows + + val validRow = listOf( + "proj123", + "SampleProject", + "A sample project", + "[state1,state2]", + "[task1,task2]" + ) + val validRowEmptyDescription = listOf( + "proj123", + "SampleProject", + "", + "[state1,state2]", + "[task1,task2]" + ) + val validRowEmptyStatesId = listOf( + "proj123", + "SampleProject", + "A sample project", + "[]", + "[task1,task2]" + ) + val validRowEmptyTasksId = listOf( + "proj123", + "SampleProject", + "A sample project", + "[state1,state2]", + "[]" + ) + val invalidRowEmptyId = listOf( + "", + "SampleProject", + "A sample project", + "[state1,state2]", + "[task1,task2]" + ) + val invalidRowEmptyName = listOf( + "proj123", + "", + "A sample project", + "[state1,state2]", + "[task1,task2]" + ) + + //endregion + } +} \ No newline at end of file diff --git a/src/test/kotlin/data/schema/StateSchemaTest.kt b/src/test/kotlin/data/schema/StateSchemaTest.kt new file mode 100644 index 0000000..2a37d73 --- /dev/null +++ b/src/test/kotlin/data/schema/StateSchemaTest.kt @@ -0,0 +1,182 @@ +package data.schema + +import com.berlin.data.schema.StateSchema +import com.berlin.domain.model.State +import com.google.common.truth.Truth.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +class StateSchemaTest { + + private lateinit var stateSchema: StateSchema + + @BeforeEach + fun setup() { + stateSchema = fakeStateSchema() + } + + //region create object + + @Test + fun `should throw IllegalArgumentException when try to create object with blank file name`() { + //when //then + assertThrows { + stateSchema = StateSchema("", listOf("a", "b", "c")) + } + } + + @Test + fun `should throw IllegalArgumentException when try to create object with invalid size header`() { + //when //then + assertThrows { + stateSchema = StateSchema("test.csv", listOf("a", "b")) + } + } + + //endregion + + //region toRow + + @Test + fun `toRow should return list of valid state attributes when valid state passed`() { + //when + val result = stateSchema.toRow(validState) + //then + assertThat(result).isEqualTo(validRow) + } + + @Test + fun `toRow should return empty list when invalid state passed miss id attribute`() { + //when + val result = stateSchema.toRow(invalidStateEmptyId) + //then + assertThat(result).isEmpty() + } + + @Test + fun `toRow should return empty list when invalid state passed miss name attribute`() { + //when + val result = stateSchema.toRow(invalidStateEmptyName) + //then + assertThat(result).isEmpty() + } + + @Test + fun `toRow should return empty list when invalid state passed miss projectId attribute`() { + //when + val result = stateSchema.toRow(invalidStateEmptyProjectId) + //then + assertThat(result).isEmpty() + } + + //endregion + + //region fromRow + + @Test + fun `fromRow should return state when valid row passed`() { + //when + val result = stateSchema.fromRow(validRow) + //then + assertThat(result).isEqualTo(validState) + } + + @Test + fun `fromRow should return null when invalid row passed miss id column`() { + //when + val result = stateSchema.fromRow(invalidRowEmptyId) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid row passed miss name column`() { + //when + val result = stateSchema.fromRow(invalidRowEmptyName) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid row passed miss projectId column`() { + //when + val result = stateSchema.fromRow(invalidRowEmptyProjectId) + //then + assertThat(result).isNull() + } + + //endregion + + //region getId + + @Test + fun `getId should return id of state passed`() { + //when + val result = stateSchema.getId(validState) + //then + assertThat(result).isEqualTo(validState.id) + } + + @Test + fun `getId should return null when state passed have empty id`() { + //when + val result = stateSchema.getId(invalidStateEmptyId) + //then + assertThat(result).isNull() + } + + //endregion + + private fun fakeStateSchema() = StateSchema("test.csv", listOf("a", "b", "c")) + + private companion object { + //region Some States + val validState = State( + id = "s1", + name = "n1", + projectId = "p1" + ) + val invalidStateEmptyId = State( + id = "", + name = "n1", + projectId = "p1" + ) + val invalidStateEmptyName = State( + id = "s1", + name = "", + projectId = "p1" + ) + val invalidStateEmptyProjectId = State( + id = "s1", + name = "n1", + projectId = "" + ) + + //endregion + + //region Some Rows + val validRow = listOf( + "s1", + "n1", + "p1" + ) + val invalidRowEmptyId = listOf( + "", + "n1", + "p1" + ) + val invalidRowEmptyName = listOf( + "s1", + "", + "p1" + ) + val invalidRowEmptyProjectId = listOf( + "s1", + "n1", + "" + ) + + //endregion + } +} \ No newline at end of file diff --git a/src/test/kotlin/data/schema/TaskSchemaTest.kt b/src/test/kotlin/data/schema/TaskSchemaTest.kt new file mode 100644 index 0000000..d529128 --- /dev/null +++ b/src/test/kotlin/data/schema/TaskSchemaTest.kt @@ -0,0 +1,311 @@ +package data.schema + +import com.berlin.data.schema.TaskSchema +import com.berlin.domain.model.Task +import com.google.common.truth.Truth.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +class TaskSchemaTest { + + private lateinit var taskSchema: TaskSchema + + @BeforeEach + fun setup() { + taskSchema = fakeTaskSchema() + } + + //region create object + + @Test + fun `should throw IllegalArgumentException when try to create object with blank file name`() { + //when //then + assertThrows { + taskSchema = TaskSchema("", listOf("a", "b", "c", "d", "e", "f", "g", "h")) + } + } + + @Test + fun `should throw IllegalArgumentException when try to create object with invalid size header`() { + //when //then + assertThrows { + taskSchema = TaskSchema("test.csv", listOf("a", "b")) + } + } + + //endregion + + //region toRow + + @Test + fun `toRow should return list of valid task attributes when valid task passed`() { + //when + val result = taskSchema.toRow(validTask) + //then + assertThat(result).isEqualTo(validRow) + } + + @Test + fun `toRow should return list of valid task attributes when task with empty description passed`() { + //when + val result = taskSchema.toRow(validTaskEmptyDescription) + //then + assertThat(result).isEqualTo(validRowEmptyDescription) + } + + @Test + fun `toRow should return empty list when invalid task passed miss id attribute`() { + //when + val result = taskSchema.toRow(invalidTaskEmptyId) + //then + assertThat(result).isEmpty() + } + + @Test + fun `toRow should return empty list when invalid task passed miss projectId attribute`() { + //when + val result = taskSchema.toRow(invalidTaskEmptyProjectId) + //then + assertThat(result).isEmpty() + } + + @Test + fun `toRow should return empty list when invalid task passed miss title attribute`() { + //when + val result = taskSchema.toRow(invalidTaskEmptyTitle) + //then + assertThat(result).isEmpty() + } + + @Test + fun `toRow should return empty list when invalid task passed miss stateId attribute`() { + //when + val result = taskSchema.toRow(invalidTaskEmptyStateId) + //then + assertThat(result).isEmpty() + } + + @Test + fun `toRow should return empty list when invalid task passed miss assign to attribute`() { + //when + val result = taskSchema.toRow(invalidTaskEmptyAssignTo) + //then + assertThat(result).isEmpty() + } + + @Test + fun `toRow should return empty list when invalid task passed miss create by attribute`() { + //when + val result = taskSchema.toRow(invalidTaskEmptycreateByUserId) + //then + assertThat(result).isEmpty() + } + + //endregion + + //region fromRow + + @Test + fun `fromRow should return task when valid row full passed`() { + //when + val result = taskSchema.fromRow(validRow) + //then + assertThat(result).isEqualTo(validTask) + } + + @Test + fun `fromRow should return task when valid row empty description passed`() { + //when + val result = taskSchema.fromRow(validRowEmptyDescription) + //then + assertThat(result).isEqualTo(validTaskEmptyDescription) + } + + @Test + fun `fromRow should return null when invalid row passed miss id column`() { + //when + val result = taskSchema.fromRow(invalidRowEmptyId) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid row passed miss projectId column`() { + //when + val result = taskSchema.fromRow(invalidRowEmptyProjectId) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid row passed miss title column`() { + //when + val result = taskSchema.fromRow(invalidRowEmptyTitle) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid row passed miss stateId column`() { + //when + val result = taskSchema.fromRow(invalidRowEmptyStateId) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid row passed miss assign to column`() { + //when + val result = taskSchema.fromRow(invalidRowEmptyAssignToUserId) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid row passed miss create by column`() { + //when + val result = taskSchema.fromRow(invalidRowEmptyCreateByUserId) + //then + assertThat(result).isNull() + } + + //endregion + + //region getId + + @Test + fun `getId should return id of task passed`() { + //when + val result = taskSchema.getId(validTask) + //then + assertThat(result).isEqualTo(validTask.id) + } + + @Test + fun `getId should return null when task passed have empty id`() { + //when + val result = taskSchema.getId(invalidTaskEmptyId) + //then + assertThat(result).isNull() + } + + //endregion + + private fun fakeTaskSchema() = TaskSchema("test.csv", listOf("a", "b", "c", "d", "e", "f", "g")) + + private companion object { + + //region Some Users id + val testUserId ="u1" + + val testUserId2 ="u2" + + //endregion + + //region Some Tasks + val validTask = Task( + id = "t1", + projectId = "p1", + title = "task1", + description = "desc", + stateId = "s1", + assignedToUserId = testUserId, + createByUserId = testUserId2 + ) + val validTaskEmptyDescription = Task( + id = "t1", + projectId = "p1", + title = "task1", + description = null, + stateId = "s1", + assignedToUserId = testUserId, + createByUserId = testUserId2, + ) + val invalidTaskEmptyId = Task( + id = "", + projectId = "p1", + title = "task1", + description = "desc", + stateId = "s1", + assignedToUserId = testUserId, + createByUserId = testUserId2, + ) + val invalidTaskEmptyProjectId = Task( + id = "t1", + projectId = "", + title = "task1", + description = "desc", + stateId = "s1", + assignedToUserId = testUserId, + createByUserId = testUserId2, + ) + val invalidTaskEmptyTitle = Task( + id = "t1", + projectId = "p1", + title = "", + description = "desc", + stateId = "s1", + assignedToUserId = testUserId, + createByUserId = testUserId2, + ) + val invalidTaskEmptyStateId = Task( + id = "t1", + projectId = "p1", + title = "task1", + description = "desc", + stateId = "", + assignedToUserId = testUserId, + createByUserId = testUserId2, + ) + val invalidTaskEmptyAssignTo = Task( + id = "t1", + projectId = "p1", + title = "task1", + description = "desc", + stateId = "s1", + assignedToUserId = "", + createByUserId = testUserId2, + ) + val invalidTaskEmptycreateByUserId = Task( + id = "t1", + projectId = "p1", + title = "task1", + description = "desc", + stateId = "s1", + assignedToUserId = testUserId, + createByUserId = "", + ) + + //endregion + + //region Some Rows + + val validRow = listOf( + "t1", "p1", "task1", "desc", "s1", "u1", "u2" + ) + val validRowEmptyDescription = listOf( + "t1", "p1", "task1", "", "s1", "u1", "u2" + ) + val invalidRowEmptyId = listOf( + "", "p1", "task1", "desc", "s1", "u1", "u2" + ) + val invalidRowEmptyProjectId = listOf( + "t1", "", "task1", "desc", "s1", "u1", "u2" + ) + val invalidRowEmptyTitle = listOf( + "t1", "p1", "", "desc", "s1", "u1", "u2" + ) + val invalidRowEmptyStateId = listOf( + "t1", "p1", "task1", "desc", "", "u1", "u2" + ) + val invalidRowEmptyAssignToUserId = listOf( + "t1", "p1", "task1", "desc", "s1", "", "u2" + ) + val invalidRowEmptyCreateByUserId = listOf( + "t1", "p1", "task1", "desc", "s1", "u1", "" + ) + + //endregion + } +} \ No newline at end of file diff --git a/src/test/kotlin/data/schema/UserSchemaTest.kt b/src/test/kotlin/data/schema/UserSchemaTest.kt new file mode 100644 index 0000000..0df1099 --- /dev/null +++ b/src/test/kotlin/data/schema/UserSchemaTest.kt @@ -0,0 +1,204 @@ +package data.schema + +import com.berlin.data.schema.UserSchema +import com.berlin.domain.model.User +import com.berlin.domain.model.UserRole +import com.google.common.truth.Truth.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + + +class UserSchemaTest { + + private lateinit var userSchema: UserSchema + + @BeforeEach + fun setup() { + userSchema = fakeUserSchema() + } + + //region create object + + @Test + fun `should throw IllegalArgumentException when try to create object with blank file name`() { + //when //then + assertThrows { + userSchema = UserSchema("", listOf("a", "b", "c", "d")) + } + } + + @Test + fun `should throw IllegalArgumentException when try to create object with invalid size header`() { + //when //then + assertThrows { + userSchema = UserSchema("test.csv", listOf("a", "b")) + } + } + + //endregion + + //region toRow + + @Test + fun `toRow should return list of valid user attributes when valid user passed`() { + //when + val result=userSchema.toRow(validUser) + //then + assertThat(result).isEqualTo(validRowAdmin) + } + + @Test + fun `toRow should return list of valid user attributes when valid user mate passed`() { + //when + val result=userSchema.toRow(validUserMate) + //then + assertThat(result).isEqualTo(validRowMate) + } + + @Test + fun `toRow should return empty list when invalid user passed miss id attribute`() { + //when + val result=userSchema.toRow(invalidUserEmptyId) + //then + assertThat(result).isEmpty() + } + + @Test + fun `toRow should return empty list when invalid user passed miss userName attribute`() { + //when + val result=userSchema.toRow(invalidUserEmptyUserName) + //then + assertThat(result).isEmpty() + } + + @Test + fun `toRow should return empty list when invalid user passed miss password attribute`() { + //when + val result=userSchema.toRow(invalidUserEmptyPass) + //then + assertThat(result).isEmpty() + } + + //endregion + + //region fromRow + + @Test + fun `fromRow should return user when valid row admin passed`() { + //when + val result=userSchema.fromRow(validRowAdmin) + //then + assertThat(result).isEqualTo(validUser) + } + + @Test + fun `fromRow should return user when valid row mate passed`() { + //when + val result=userSchema.fromRow(validRowMate) + //then + assertThat(result).isEqualTo(validUserMate) + } + + @Test + fun `fromRow should return null when invalid row passed miss id column`() { + //when + val result=userSchema.fromRow(invalidRowEmptyId) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid user passed miss userName column`() { + //when + val result=userSchema.fromRow(invalidRowEmptyUserName) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid user passed miss password column`() { + //when + val result=userSchema.fromRow(invalidRowEmptyPass) + //then + assertThat(result).isNull() + } + + @Test + fun `fromRow should return null when invalid user passed miss role column`() { + //when + val result=userSchema.fromRow(invalidRowEmptyRole) + //then + assertThat(result).isNull() + } + + //endregion + + //region getId + + @Test + fun `getId should return id of user passed`() { + //when + val result=userSchema.getId(validUser) + //then + assertThat(result).isEqualTo(validUser.id) + } + + @Test + fun `getId should return null when user passed have empty id`() { + //when + val result=userSchema.getId(invalidUserEmptyId) + //then + assertThat(result).isNull() + } + + //endregion + + private fun fakeUserSchema() = UserSchema("test.csv", listOf("a", "b", "c", "d")) + + private companion object { + + //region Some Users + + val validUserMate = User( + id = "abcs123", userName = "marwanMahmoud", password = "ui76654898", role = UserRole.MATE + ) + val validUser = User( + id = "abcs123", userName = "marwanMahmoud", password = "ui76654898", role = UserRole.ADMIN + ) + val invalidUserEmptyId = User( + id = "", userName = "marwanMahmoud", password = "ui76654898", role = UserRole.ADMIN + ) + val invalidUserEmptyUserName = User( + id = "abcs123", userName = "", password = "ui76654898", role = UserRole.ADMIN + ) + val invalidUserEmptyPass = User( + id = "abcs123", userName = "marwanMahmoud", password = "", role = UserRole.ADMIN + ) + + //endregion + + //region Some Rows + + val validRowAdmin = listOf( + "abcs123", "marwanMahmoud", "ui76654898", UserRole.ADMIN.toString() + ) + val validRowMate = listOf( + "abcs123", "marwanMahmoud", "ui76654898", UserRole.MATE.toString() + ) + val invalidRowEmptyId = listOf( + "", "marwanMahmoud", "ui76654898", UserRole.ADMIN.toString() + ) + val invalidRowEmptyUserName = listOf( + "abcs123", "", "ui76654898", UserRole.ADMIN.toString() + ) + val invalidRowEmptyPass = listOf( + "abcs123", "marwanMahmoud", "", UserRole.ADMIN.toString() + ) + val invalidRowEmptyRole = listOf( + "abcs123", "marwanMahmoud", "ui76654898", "" + ) + + //endregion + } +} \ No newline at end of file