Skip to content

Commit

Permalink
🥅 Add UUID field handling to UseCsvParser
Browse files Browse the repository at this point in the history
Enhance UseCsvParser to handle an optional UUID field, generating new
UUIDs when absent. Introduce corresponding tests to ensure proper UUID
parsing and generation.

Signed-off-by: Leonardo Colman Lopes <[email protected]>
  • Loading branch information
LeoColman committed Oct 23, 2024
1 parent 0dda2a9 commit 364f377
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package br.com.colman.petals.use.io

import android.content.Context
import android.content.Intent
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.result.ActivityResult
import androidx.core.net.toUri
import androidx.test.core.app.ApplicationProvider
import br.com.colman.kotest.FunSpec
import br.com.colman.petals.koin
import br.com.colman.petals.use.io.input.UseCsvFileImporter
import br.com.colman.petals.use.io.output.UseExporter
import io.kotest.core.spec.IsolationMode.InstancePerTest
import io.kotest.matchers.file.shouldHaveSameStructureAndContentAs
import io.mockk.mockk
import io.mockk.verify
import java.io.File
import java.time.LocalDate
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin

class UseIOModuleTest : FunSpec({

val useCsvFileImporter = koin.get<UseCsvFileImporter>()
val useExporter = koin.get<UseExporter>()

test("should import and export data maintaining integrity") {
val inputFile = File(ApplicationProvider.getApplicationContext<Context>().filesDir, "test_input.csv")

inputFile.writeText(
"""
date,amount,cost_per_gram,id
2024-03-21T19:01:47.163,0.08,22.2,80204597-00eb-4412-b7ee-223388806fe2
""".trimIndent()
)

useCsvFileImporter.importCsvFile(inputFile.toUri())

val mockLauncher = mockk<ManagedActivityResultLauncher<Intent, ActivityResult>>(relaxed = true)

useExporter.exportUses(mockLauncher)

verify {
mockLauncher.launch(match { intent ->
intent.action == Intent.ACTION_SEND &&
intent.type == "text/plain" &&
intent.flags == Intent.FLAG_GRANT_READ_URI_PERMISSION
})
}

val exportsDir = File(ApplicationProvider.getApplicationContext<Context>().filesDir, "exports")
val expectedFileName = "PetalsExport-${LocalDate.now()}.csv"
val exportedFile = File(exportsDir, expectedFileName)


inputFile shouldHaveSameStructureAndContentAs exportedFile

}

})
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,24 @@ package br.com.colman.petals.use.io.input
import br.com.colman.petals.use.repository.Use
import com.github.doyaaaaaken.kotlincsv.dsl.csvReader
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME
import java.util.UUID.randomUUID

object UseCsvParser {
private val csvReader = csvReader()

fun parse(line: String): Result<Use> = runCatching {
val (date, amount, cost) = csvReader.readAll(line).single()
val values = csvReader.readAll(line).single()

val dateTime = LocalDateTime.parse(date, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
val dateTime = parseDateTime(values[0])
val amount = values[1].toBigDecimal()
val cost = values[2].toBigDecimal()
val id = parseOrGenerateUUID(values.getOrNull(3))

Use(dateTime, amount.toBigDecimal(), cost.toBigDecimal())
Use(dateTime, amount, cost, id)
}

private fun parseDateTime(date: String) = LocalDateTime.parse(date, ISO_LOCAL_DATE_TIME)

private fun parseOrGenerateUUID(uuid: String?) = if (uuid.isNullOrBlank()) randomUUID().toString() else uuid
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import br.com.colman.petals.use.io.UseCsvArb
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.result.shouldBeFailure
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldBeUUID
import io.kotest.property.arbitrary.filter
import io.kotest.property.arbitrary.next
import io.kotest.property.arbitrary.take
Expand Down Expand Up @@ -36,6 +37,30 @@ class UseCsvParserTest : FunSpec({
UseCsvParser.parse(useCsv).shouldBeFailure()
}

test("Parses the id field if it's present") {
val use = UseArb.next()
val useCsv = use.columns().joinToString(",")
val parsed = UseCsvParser.parse(useCsv)

parsed.getOrThrow().id shouldBe use.id
}

test("Creates new id if id field is empty") {
val use = UseArb.next().copy(id = "")
val useCsv = use.columns().joinToString(",")
val parsed = UseCsvParser.parse(useCsv)

parsed.getOrThrow().id.shouldBeUUID()
}

test("Creates new id if id field is not present") {
val use = UseArb.next().copy(id = "")
val useCsv = use.columns().dropLast(1).joinToString(",")
val parsed = UseCsvParser.parse(useCsv)

parsed.getOrThrow().id.shouldBeUUID()
}

test("Parses successfully even if extra fields are present") {
val use = UseArb.next()
val extraField = "extra"
Expand Down

0 comments on commit 364f377

Please sign in to comment.