diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 2b4b0cf..6362246 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -26,3 +26,6 @@ jobs:
coverage:
uses: ./.github/workflows/coverage.yml
+
+ code-style:
+ uses: ./.github/workflows/code-style.yml
\ No newline at end of file
diff --git a/.github/workflows/code-style.yml b/.github/workflows/code-style.yml
new file mode 100644
index 0000000..7ad3489
--- /dev/null
+++ b/.github/workflows/code-style.yml
@@ -0,0 +1,24 @@
+on:
+ workflow_call:
+
+jobs:
+ code-style:
+ name: 👔 Code style
+ runs-on: ubuntu-24.04
+
+ steps:
+ - uses: actions/checkout@v4
+ - uses: ./.github/actions/setup-jdk-gradle
+
+ - name: 🕵🏻♂️ Detekt
+ run: |
+ ./gradlew --no-daemon --parallel --console=plain \
+ detekt
+ echo "### Detekt Report" >> $GITHUB_STEP_SUMMARY
+ if [ -f build/reports/detekt/detekt.txt ]; then
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ cat build/reports/detekt/detekt.txt >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ else
+ echo "No report found." >> $GITHUB_STEP_SUMMARY
+ fi
\ No newline at end of file
diff --git a/.idea/detekt.xml b/.idea/detekt.xml
new file mode 100644
index 0000000..03d0954
--- /dev/null
+++ b/.idea/detekt.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-test-util/build.gradle.kts b/android-test-util/build.gradle.kts
index f16e786..da3fffe 100644
--- a/android-test-util/build.gradle.kts
+++ b/android-test-util/build.gradle.kts
@@ -20,7 +20,6 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.jetbrains.kotlin.android)
diff --git a/android-test-util/src/main/kotlin/net/opatry/test/util/android/KoinTestRule.kt b/android-test-util/src/main/kotlin/net/opatry/test/util/android/KoinTestRule.kt
index 0e3868e..851b6c3 100644
--- a/android-test-util/src/main/kotlin/net/opatry/test/util/android/KoinTestRule.kt
+++ b/android-test-util/src/main/kotlin/net/opatry/test/util/android/KoinTestRule.kt
@@ -49,4 +49,4 @@ class KoinTestRule(
override fun finished(description: Description) {
unloadKoinModules(modules)
}
-}
\ No newline at end of file
+}
diff --git a/android-test-util/src/main/kotlin/net/opatry/test/util/android/navigation/NavHostControllerTestExt.kt b/android-test-util/src/main/kotlin/net/opatry/test/util/android/navigation/NavHostControllerTestExt.kt
index 9e17d88..72e2cad 100644
--- a/android-test-util/src/main/kotlin/net/opatry/test/util/android/navigation/NavHostControllerTestExt.kt
+++ b/android-test-util/src/main/kotlin/net/opatry/test/util/android/navigation/NavHostControllerTestExt.kt
@@ -9,4 +9,4 @@ inline fun NavHostController.assertRoute() {
assertThat(currentDestination?.hasRoute())
.withFailMessage("Expected %s route but current route is %s", T::class.java.name, currentDestination?.route)
.isTrue()
-}
\ No newline at end of file
+}
diff --git a/build.gradle.kts b/build.gradle.kts
index 7f2c30d..5252fbc 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -20,6 +20,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+import io.gitlab.arturbosch.detekt.Detekt
import kotlinx.kover.gradle.plugin.dsl.CoverageUnit
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
@@ -34,6 +35,7 @@ plugins {
alias(libs.plugins.android.library) apply false
alias(libs.plugins.about.libraries) apply false
alias(libs.plugins.kover)
+ alias(libs.plugins.detekt)
}
val koverProjects = listOf(
@@ -100,6 +102,33 @@ kover {
}
}
+allprojects {
+ project.afterEvaluate {
+ apply(plugin = libs.plugins.detekt.get().pluginId)
+ detekt {
+ config.setFrom("$rootDir/detekt.yml")
+ buildUponDefaultConfig = true
+ allRules = true
+ parallel = true
+ ignoreFailures = false
+ }
+
+ dependencies {
+ detektPlugins(projects.detektRules)
+ }
+ }
+
+ tasks.withType { dependsOn(":detekt-rules:assemble") }
+ tasks.withType().configureEach {
+ reports {
+ txt.required.set(true)
+ html.required.set(false)
+ xml.required.set(false)
+ sarif.required.set(false)
+ }
+ }
+}
+
subprojects {
tasks {
findByName("test") ?: return@tasks
diff --git a/detekt-rules/build.gradle.kts b/detekt-rules/build.gradle.kts
new file mode 100644
index 0000000..2e1909f
--- /dev/null
+++ b/detekt-rules/build.gradle.kts
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2025 Olivier Patry
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the Software
+ * is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+plugins {
+ kotlin("jvm")
+}
+
+dependencies {
+ compileOnly(libs.detekt.api)
+ testImplementation(libs.detekt.test)
+ testImplementation(libs.junit)
+ testImplementation(libs.assertj.core)
+}
\ No newline at end of file
diff --git a/detekt-rules/src/main/kotlin/net/opatry/detekt/CleanArchitectureBoundaryRule.kt b/detekt-rules/src/main/kotlin/net/opatry/detekt/CleanArchitectureBoundaryRule.kt
new file mode 100644
index 0000000..a1ac3af
--- /dev/null
+++ b/detekt-rules/src/main/kotlin/net/opatry/detekt/CleanArchitectureBoundaryRule.kt
@@ -0,0 +1,61 @@
+package net.opatry.detekt
+
+import io.gitlab.arturbosch.detekt.api.CodeSmell
+import io.gitlab.arturbosch.detekt.api.Config
+import io.gitlab.arturbosch.detekt.api.Debt
+import io.gitlab.arturbosch.detekt.api.Entity
+import io.gitlab.arturbosch.detekt.api.Issue
+import io.gitlab.arturbosch.detekt.api.Rule
+import io.gitlab.arturbosch.detekt.api.Severity
+import org.jetbrains.kotlin.psi.KtImportDirective
+
+class CleanArchitectureBoundaryRule(config: Config = Config.empty) : Rule(config) {
+ private companion object {
+ private val violations = mapOf(
+ ".domain." to listOf(".presentation.", ".data.", ".ui."),
+ ".presentation." to listOf(".data.", ".ui."),
+ ".ui." to listOf(".domain.", ".data."),
+ ".navigation." to listOf(".domain.", ".data."),
+ )
+ }
+
+ override val issue = Issue(
+ id = "CleanArchitectureBoundaryRule",
+ severity = Severity.CodeSmell,
+ description = "Clean Architecture boundary violation detected",
+ debt = Debt.TWENTY_MINS,
+ )
+
+ override fun visitImportDirective(importDirective: KtImportDirective) {
+ super.visitImportDirective(importDirective)
+
+ val importPath = importDirective.importPath?.pathStr ?: return
+ val currentFile = importDirective.containingKtFile
+ val currentPackage = currentFile.packageFqName.asString()
+
+ checkArchitectureBoundaries(currentPackage, importPath, importDirective)
+ }
+
+ private fun checkArchitectureBoundaries(
+ currentPackage: String,
+ importPath: String,
+ importDirective: KtImportDirective,
+ ) {
+ violations
+ .filterKeys { "$currentPackage.".contains(it) }
+ .forEach { (fromLayer, toLayers) ->
+ toLayers
+ .filter { importPath.contains(it) }
+ .forEach { toLayer ->
+ val message = "Layer ${fromLayer.trim('.')} should not import from ${toLayer.trim('.')} layer"
+ report(
+ CodeSmell(
+ issue = issue,
+ entity = Entity.from(importDirective),
+ message = message,
+ )
+ )
+ }
+ }
+ }
+}
diff --git a/detekt-rules/src/main/kotlin/net/opatry/detekt/CustomRuleSetProvider.kt b/detekt-rules/src/main/kotlin/net/opatry/detekt/CustomRuleSetProvider.kt
new file mode 100644
index 0000000..fb1ca4c
--- /dev/null
+++ b/detekt-rules/src/main/kotlin/net/opatry/detekt/CustomRuleSetProvider.kt
@@ -0,0 +1,16 @@
+package net.opatry.detekt
+
+import io.gitlab.arturbosch.detekt.api.Config
+import io.gitlab.arturbosch.detekt.api.RuleSet
+import io.gitlab.arturbosch.detekt.api.RuleSetProvider
+
+class CustomRuleSetProvider : RuleSetProvider {
+ override val ruleSetId: String = "h2go-rules"
+
+ override fun instance(config: Config) = RuleSet(
+ ruleSetId,
+ listOf(
+ CleanArchitectureBoundaryRule(config)
+ )
+ )
+}
diff --git a/detekt-rules/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider b/detekt-rules/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider
new file mode 100644
index 0000000..0edd05d
--- /dev/null
+++ b/detekt-rules/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider
@@ -0,0 +1 @@
+net.opatry.detekt.CustomRuleSetProvider
\ No newline at end of file
diff --git a/detekt-rules/src/test/java/net/opatry/detetk/CleanArchitectureBoundaryRuleTest.kt b/detekt-rules/src/test/java/net/opatry/detetk/CleanArchitectureBoundaryRuleTest.kt
new file mode 100644
index 0000000..cc13b67
--- /dev/null
+++ b/detekt-rules/src/test/java/net/opatry/detetk/CleanArchitectureBoundaryRuleTest.kt
@@ -0,0 +1,344 @@
+package net.opatry.detetk
+
+import io.gitlab.arturbosch.detekt.api.Config
+import io.gitlab.arturbosch.detekt.api.Finding
+import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest
+import io.gitlab.arturbosch.detekt.test.compileAndLint
+import net.opatry.detekt.CleanArchitectureBoundaryRule
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.Test
+
+@KotlinCoreEnvironmentTest
+class CleanArchitectureBoundaryRuleTest {
+
+ private val rule = CleanArchitectureBoundaryRule(Config.empty)
+
+ @Test
+ fun `should detect domain layer importing presentation layer`() {
+ val code = """
+ package com.example.domain.usecase
+
+ import com.example.presentation.ViewModel
+ import com.example.domain.model.User
+
+ class GetUserUseCase
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings.map(Finding::message)).containsExactlyInAnyOrder(
+ "Layer domain should not import from presentation layer",
+ )
+ }
+
+ @Test
+ fun `should detect domain layer importing data layer`() {
+ val code = """
+ package com.example.domain.repository
+
+ import com.example.data.database.UserDao
+ import com.example.domain.model.User
+
+ interface UserRepository
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings.map(Finding::message)).containsExactlyInAnyOrder(
+ "Layer domain should not import from data layer",
+ )
+ }
+
+ @Test
+ fun `should detect domain layer importing ui layer`() {
+ val code = """
+ package com.example.domain.usecase
+
+ import com.example.ui.components.Button
+ import com.example.domain.model.User
+
+ class GetUserUseCase
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings.map(Finding::message)).containsExactlyInAnyOrder(
+ "Layer domain should not import from ui layer",
+ )
+ }
+
+ @Test
+ fun `should detect presentation layer importing data layer`() {
+ val code = """
+ package com.example.presentation.viewmodel
+
+ import com.example.data.repository.UserRepositoryImpl
+ import com.example.domain.usecase.GetUserUseCase
+
+ class UserViewModel(
+ private val getUserUseCase: GetUserUseCase
+ )
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings.map(Finding::message)).containsExactlyInAnyOrder(
+ "Layer presentation should not import from data layer",
+ )
+ }
+
+ @Test
+ fun `should detect presentation layer importing ui layer`() {
+ val code = """
+ package com.example.presentation.mapper
+
+ import com.example.ui.model.UserUiModel
+ import com.example.domain.model.User
+
+ class UserMapper {
+ fun mapToUi(user: User): UserUiModel = UserUiModel()
+ }
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings.map(Finding::message)).containsExactlyInAnyOrder(
+ "Layer presentation should not import from ui layer",
+ )
+ }
+
+ @Test
+ fun `should detect ui layer importing domain layer`() {
+ val code = """
+ package com.example.ui.screen
+
+ import com.example.domain.model.User
+ import com.example.presentation.viewmodel.UserViewModel
+
+ class UserScreen(
+ private val viewModel: UserViewModel
+ )
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings.map(Finding::message)).containsExactlyInAnyOrder(
+ "Layer ui should not import from domain layer",
+ )
+ }
+
+ @Test
+ fun `should detect ui layer importing data layer`() {
+ val code = """
+ package com.example.ui.components
+
+ import com.example.data.database.UserDao
+ import com.example.presentation.viewmodel.UserViewModel
+
+ class UserComponent
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings.map(Finding::message)).containsExactlyInAnyOrder(
+ "Layer ui should not import from data layer",
+ )
+ }
+
+ @Test
+ fun `should detect multiple violations in single file`() {
+ val code = """
+ package com.example.domain.usecase
+
+ import com.example.presentation.ViewModel
+ import com.example.data.repository.UserRepository
+ import com.example.ui.model.UserUiModel
+ import com.example.domain.model.User
+
+ class GetUserUseCase
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings.map(Finding::message)).containsExactlyInAnyOrder(
+ "Layer domain should not import from presentation layer",
+ "Layer domain should not import from data layer",
+ "Layer domain should not import from ui layer",
+ )
+ }
+
+ @Test
+ fun `should detect violation when package name ends with forbidden package pattern`() {
+ val code = """
+ package com.example.domain
+
+ import com.example.ui.UserUiModel
+
+ class GetUserUseCase
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings.map(Finding::message)).containsExactlyInAnyOrder(
+ "Layer domain should not import from ui layer",
+ )
+ }
+
+ @Test
+ fun `should allow valid domain layer imports`() {
+ val code = """
+ package com.example.domain.usecase
+
+ import com.example.domain.model.User
+ import com.example.domain.repository.UserRepository
+ import java.util.Date
+ import kotlin.collections.List
+
+ class GetUserUseCase
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings).isEmpty()
+ }
+
+ @Test
+ fun `should allow valid presentation layer imports`() {
+ val code = """
+ package com.example.presentation.viewmodel
+
+ import com.example.domain.usecase.GetUserUseCase
+ import com.example.domain.model.User
+ import com.example.presentation.mapper.UserMapper
+ import kotlinx.coroutines.flow.Flow
+
+ class UserViewModel
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings).isEmpty()
+ }
+
+ @Test
+ fun `should allow valid ui layer imports`() {
+ val code = """
+ package com.example.ui.screen
+
+ import com.example.presentation.viewmodel.UserViewModel
+ import com.example.ui.components.Button
+ import androidx.compose.runtime.Composable
+ import androidx.compose.material3.Text
+
+ @Composable
+ fun UserScreen(
+ viewModel: UserViewModel
+ ) {
+ Text("Hello")
+ }
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings).isEmpty()
+ }
+
+ @Test
+ fun `should allow valid data layer imports`() {
+ val code = """
+ package com.example.data.repository
+
+ import com.example.domain.model.User
+ import com.example.domain.repository.UserRepository
+ import com.example.data.database.UserDao
+ import com.example.data.network.UserApi
+
+ class UserRepositoryImpl(
+ private val userDao: UserDao,
+ private val userApi: UserApi
+ ) : UserRepository {
+ override fun getUser(): User = User()
+ }
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings).isEmpty()
+ }
+
+ @Test
+ fun `should handle nested package structures`() {
+ val code = """
+ package com.example.feature.user.domain.usecase
+
+ import com.example.feature.user.presentation.viewmodel.UserViewModel
+ import com.example.feature.user.domain.model.User
+
+ class GetUserUseCase
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings.map(Finding::message)).containsExactlyInAnyOrder(
+ "Layer domain should not import from presentation layer",
+ )
+ }
+
+ @Test
+ fun `should handle different module structures`() {
+ val code = """
+ package com.example.moduleA.domain.service
+
+ import com.example.moduleB.data.repository.UserRepository
+ import com.example.moduleA.domain.model.User
+
+ class UserService
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings.map(Finding::message)).containsExactlyInAnyOrder(
+ "Layer domain should not import from data layer",
+ )
+ }
+
+ @Test
+ fun `should ignore non-architecture related imports`() {
+ val code = """
+ package com.example.domain.usecase
+
+ import java.util.UUID
+ import kotlin.collections.List
+ import kotlinx.coroutines.flow.Flow
+ import javax.inject.Inject
+ import com.google.gson.Gson
+ import com.example.domain.model.User
+
+ class GetUserUseCase @Inject constructor() {
+ fun execute(): Flow> = TODO()
+ }
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings).isEmpty()
+ }
+
+ @Test
+ fun `should handle star imports`() {
+ val code = """
+ package com.example.domain.usecase
+
+ import com.example.presentation.viewmodel.*
+ import com.example.domain.model.User
+
+ class GetUserUseCase
+ """.trimIndent()
+
+ val findings = rule.compileAndLint(code)
+
+ assertThat(findings.map(Finding::message)).containsExactlyInAnyOrder(
+ "Layer domain should not import from presentation layer",
+ )
+ }
+}
diff --git a/detekt.yml b/detekt.yml
new file mode 100644
index 0000000..5bb0a3a
--- /dev/null
+++ b/detekt.yml
@@ -0,0 +1,39 @@
+processors:
+ active: true
+
+naming:
+ FunctionNaming:
+ active: true
+ ignoreAnnotated: ['Composable']
+ functionPattern: '^[a-z][A-Za-z0-9]*$'
+ MatchingDeclarationName:
+ active: false
+ excludes: ['**/ui/**']
+ ignoreAnnotated: ['Composable', 'VisibleForTesting']
+
+style:
+ UnusedPrivateMember:
+ active: true
+ ignoreAnnotated: ['Preview', 'PreviewLightDark']
+ MaxLineLength:
+ active: true
+ maxLineLength: 120
+ excludePackageStatements: true
+ excludeImportStatements: true
+ excludeCommentStatements: true
+ ignoreAnnotated: ['Test']
+
+complexity:
+ LongMethod:
+ active: true
+ ignoreAnnotated: ['Composable', 'Test']
+ threshold: 60
+
+performance:
+ SpreadOperator:
+ active: false
+
+h2go-rules:
+ active: true
+ CleanArchitectureBoundaryRule:
+ active: true
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 0f079c6..a591f83 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -23,6 +23,7 @@ junit4 = "4.13.2"
junit = "5.10.2"
assertj = "3.27.3"
kover = "0.9.1"
+detekt = "1.23.8"
androidx-test-runner = "1.6.2"
[libraries]
@@ -80,6 +81,9 @@ junit4 = { group = "junit", name = "junit", version.ref = "junit4" }
junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
assertj-core = { module = "org.assertj:assertj-core", version.ref = "assertj" }
+detekt-api = { module = "io.gitlab.arturbosch.detekt:detekt-api", version.ref = "detekt" }
+detekt-test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version.ref = "detekt" }
+
[bundles]
mockito = [
"mockito-core",
@@ -98,3 +102,4 @@ ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
androidx-room = { id = "androidx.room", version.ref = "room" }
about-libraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "about-libraries" }
kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
+detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
diff --git a/h2go-app/build.gradle.kts b/h2go-app/build.gradle.kts
index a704880..ea0b938 100644
--- a/h2go-app/build.gradle.kts
+++ b/h2go-app/build.gradle.kts
@@ -87,11 +87,11 @@ android {
kotlin {
jvmToolchain(17)
}
-
+
buildFeatures {
compose = true
}
-
+
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
diff --git a/h2go-app/src/androidTest/java/net/opatry/h2go/app/navigation/MainNavigationTest.kt b/h2go-app/src/androidTest/java/net/opatry/h2go/app/navigation/MainNavigationTest.kt
index 05bb512..0726647 100644
--- a/h2go-app/src/androidTest/java/net/opatry/h2go/app/navigation/MainNavigationTest.kt
+++ b/h2go-app/src/androidTest/java/net/opatry/h2go/app/navigation/MainNavigationTest.kt
@@ -122,4 +122,4 @@ class MainNavigationTest {
// Then
navController.assertRoute()
}
-}
\ No newline at end of file
+}
diff --git a/h2go-app/src/androidTest/java/net/opatry/h2go/data/di/databaseTestModule.kt b/h2go-app/src/androidTest/java/net/opatry/h2go/data/di/databaseTestModule.kt
index 7d4ad50..f4a12e3 100644
--- a/h2go-app/src/androidTest/java/net/opatry/h2go/data/di/databaseTestModule.kt
+++ b/h2go-app/src/androidTest/java/net/opatry/h2go/data/di/databaseTestModule.kt
@@ -35,4 +35,4 @@ val databaseTestModule = module {
single {
get().userPreferencesDao()
}
-}
\ No newline at end of file
+}
diff --git a/h2go-app/src/main/java/net/opatry/h2go/app/H2GoApplication.kt b/h2go-app/src/main/java/net/opatry/h2go/app/H2GoApplication.kt
index 9a66516..f2c5ce4 100644
--- a/h2go-app/src/main/java/net/opatry/h2go/app/H2GoApplication.kt
+++ b/h2go-app/src/main/java/net/opatry/h2go/app/H2GoApplication.kt
@@ -42,4 +42,4 @@ class H2GoApplication : Application(), KoinStartup {
onboardingModule,
)
}
-}
\ No newline at end of file
+}
diff --git a/h2go-app/src/main/java/net/opatry/h2go/app/data/H2GoDatabase.kt b/h2go-app/src/main/java/net/opatry/h2go/app/data/H2GoDatabase.kt
index fbf4400..b004e22 100644
--- a/h2go-app/src/main/java/net/opatry/h2go/app/data/H2GoDatabase.kt
+++ b/h2go-app/src/main/java/net/opatry/h2go/app/data/H2GoDatabase.kt
@@ -35,4 +35,4 @@ import net.opatry.h2go.preference.data.entity.UserPreferencesEntity
)
abstract class H2GoDatabase : RoomDatabase() {
abstract fun userPreferencesDao(): UserPreferencesDao
-}
\ No newline at end of file
+}
diff --git a/h2go-app/src/main/java/net/opatry/h2go/app/data/di/databaseModule.kt b/h2go-app/src/main/java/net/opatry/h2go/app/data/di/databaseModule.kt
index 36509a4..8b22ce7 100644
--- a/h2go-app/src/main/java/net/opatry/h2go/app/data/di/databaseModule.kt
+++ b/h2go-app/src/main/java/net/opatry/h2go/app/data/di/databaseModule.kt
@@ -33,4 +33,4 @@ val databaseModule = module {
}
single { get().userPreferencesDao() }
-}
\ No newline at end of file
+}
diff --git a/h2go-app/src/main/java/net/opatry/h2go/app/navigation/MainNavigation.kt b/h2go-app/src/main/java/net/opatry/h2go/app/navigation/MainNavigation.kt
index bd73003..351ee51 100644
--- a/h2go-app/src/main/java/net/opatry/h2go/app/navigation/MainNavigation.kt
+++ b/h2go-app/src/main/java/net/opatry/h2go/app/navigation/MainNavigation.kt
@@ -49,4 +49,4 @@ fun MainNavigation(navController: NavHostController = rememberNavController()) {
}
}
}
-}
\ No newline at end of file
+}
diff --git a/h2go-app/src/main/java/net/opatry/h2go/app/navigation/MainRoutes.kt b/h2go-app/src/main/java/net/opatry/h2go/app/navigation/MainRoutes.kt
index bd5207f..db4be9a 100644
--- a/h2go-app/src/main/java/net/opatry/h2go/app/navigation/MainRoutes.kt
+++ b/h2go-app/src/main/java/net/opatry/h2go/app/navigation/MainRoutes.kt
@@ -27,4 +27,4 @@ import kotlinx.serialization.Serializable
object MainRoutes {
@Serializable
data object Main
-}
\ No newline at end of file
+}
diff --git a/h2go-app/src/test/java/net/opatry/h2go/app/di/H2GoDITest.kt b/h2go-app/src/test/java/net/opatry/h2go/app/di/H2GoDITest.kt
index 408676f..fe07a6b 100644
--- a/h2go-app/src/test/java/net/opatry/h2go/app/di/H2GoDITest.kt
+++ b/h2go-app/src/test/java/net/opatry/h2go/app/di/H2GoDITest.kt
@@ -44,4 +44,4 @@ class H2GoDITest {
}
allModules.verify()
}
-}
\ No newline at end of file
+}
diff --git a/h2go-app/src/test/java/net/opatry/h2go/data/di/DatabaseModuleTest.kt b/h2go-app/src/test/java/net/opatry/h2go/data/di/DatabaseModuleTest.kt
index f080d75..fe0f577 100644
--- a/h2go-app/src/test/java/net/opatry/h2go/data/di/DatabaseModuleTest.kt
+++ b/h2go-app/src/test/java/net/opatry/h2go/data/di/DatabaseModuleTest.kt
@@ -34,4 +34,4 @@ class DatabaseModuleTest {
fun `verify database module`() {
databaseModule.verify()
}
-}
\ No newline at end of file
+}
diff --git a/onboarding/build.gradle.kts b/onboarding/build.gradle.kts
index b2bccaf..c2cae06 100644
--- a/onboarding/build.gradle.kts
+++ b/onboarding/build.gradle.kts
@@ -69,4 +69,4 @@ dependencies {
testImplementation(libs.assertj.core)
testImplementation(libs.bundles.mockito)
testImplementation(libs.koin.test)
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/di/onboardingModule.kt b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/di/onboardingModule.kt
index d55bef0..e7de291 100644
--- a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/di/onboardingModule.kt
+++ b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/di/onboardingModule.kt
@@ -38,4 +38,4 @@ val onboardingModule = module {
singleOf(::SaveInitialUserPreferencesUseCase)
singleOf(::UserVolumeUnitMapper)
viewModelOf(::PreferencesViewModel)
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/domain/CheckUserPreferencesExistUseCase.kt b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/domain/CheckUserPreferencesExistUseCase.kt
index 5806b7b..e99e8c5 100644
--- a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/domain/CheckUserPreferencesExistUseCase.kt
+++ b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/domain/CheckUserPreferencesExistUseCase.kt
@@ -29,4 +29,4 @@ class CheckUserPreferencesExistUseCase(
private val userPreferencesRepository: UserPreferencesRepository,
) {
suspend operator fun invoke(): Boolean = userPreferencesRepository.getUserPreferences().firstOrNull() != null
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/domain/SaveInitialUserPreferencesUseCase.kt b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/domain/SaveInitialUserPreferencesUseCase.kt
index d5194f7..bc0270a 100644
--- a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/domain/SaveInitialUserPreferencesUseCase.kt
+++ b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/domain/SaveInitialUserPreferencesUseCase.kt
@@ -50,4 +50,4 @@ class SaveInitialUserPreferencesUseCase(
)
userPreferencesRepository.updateUserPreferences(preferences)
}
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/navigation/OnboardingNavigation.kt b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/navigation/OnboardingNavigation.kt
index a56b63c..0bd855a 100644
--- a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/navigation/OnboardingNavigation.kt
+++ b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/navigation/OnboardingNavigation.kt
@@ -51,4 +51,4 @@ fun NavGraphBuilder.onboardingNavigation(
)
}
}
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/navigation/OnboardingRoutes.kt b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/navigation/OnboardingRoutes.kt
index 71a1ad1..5be7585 100644
--- a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/navigation/OnboardingRoutes.kt
+++ b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/navigation/OnboardingRoutes.kt
@@ -32,4 +32,4 @@ object OnboardingRoutes {
@Serializable
data object Preferences
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/PreferencesEvent.kt b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/PreferencesEvent.kt
index edaa17a..b89de5a 100644
--- a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/PreferencesEvent.kt
+++ b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/PreferencesEvent.kt
@@ -3,4 +3,4 @@ package net.opatry.h2go.onboarding.presentation
sealed interface PreferencesEvent {
data object NavigateToMain : PreferencesEvent
data class Error(val message: String): PreferencesEvent
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/PreferencesUiState.kt b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/PreferencesUiState.kt
index 68647d3..dba3430 100644
--- a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/PreferencesUiState.kt
+++ b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/PreferencesUiState.kt
@@ -31,4 +31,4 @@ data class PreferencesUiState(
val notificationsFrequency: Duration,
val notificationsFrequencyBounds: ClosedRange,
val isSaving: Boolean,
-)
\ No newline at end of file
+)
diff --git a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/UserVolumeUnit.kt b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/UserVolumeUnit.kt
index fcfd56a..f0ca7a1 100644
--- a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/UserVolumeUnit.kt
+++ b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/UserVolumeUnit.kt
@@ -19,4 +19,4 @@ sealed interface UserVolumeUnit {
override val labelRes: Int
get() = R.string.onboarding_preferences_volume_unit_oz
}
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/UserVolumeUnitMapper.kt b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/UserVolumeUnitMapper.kt
index 5f9881d..e897ba3 100644
--- a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/UserVolumeUnitMapper.kt
+++ b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/UserVolumeUnitMapper.kt
@@ -12,4 +12,4 @@ class UserVolumeUnitMapper {
UserVolumeUnit.Milliliter -> VolumeUnit.Milliliter
UserVolumeUnit.Oz -> VolumeUnit.Oz
}
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/WelcomeUiState.kt b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/WelcomeUiState.kt
index b031f24..a1c03c7 100644
--- a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/WelcomeUiState.kt
+++ b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/presentation/WelcomeUiState.kt
@@ -27,4 +27,4 @@ sealed interface WelcomeUiState {
data object Idle : WelcomeUiState
data object ShowWelcome : WelcomeUiState
data object NavigateToMain : WelcomeUiState
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/ui/PreferencesScreen.kt b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/ui/PreferencesScreen.kt
index f8296b7..6f64f53 100644
--- a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/ui/PreferencesScreen.kt
+++ b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/ui/PreferencesScreen.kt
@@ -117,7 +117,7 @@ fun PreferencesScreen(
}
@Composable
-fun PreferencesScreen(
+internal fun PreferencesScreen(
uiState: PreferencesUiState,
onVolumeUnitSelected: (UserVolumeUnit) -> Unit,
onNotificationsEnabledChanged: (Boolean) -> Unit,
@@ -294,4 +294,4 @@ private fun PreferencesScreenPreview(
)
}
}
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/ui/WelcomeScreen.kt b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/ui/WelcomeScreen.kt
index 2a77970..2079563 100644
--- a/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/ui/WelcomeScreen.kt
+++ b/onboarding/src/main/kotlin/net/opatry/h2go/onboarding/ui/WelcomeScreen.kt
@@ -73,7 +73,7 @@ fun WelcomeScreen(
}
@Composable
-fun WelcomeScreen(
+internal fun WelcomeScreen(
onContinueClicked: () -> Unit,
) {
Column(
@@ -114,4 +114,4 @@ private fun WelcomeScreenContentPreview() {
)
}
}
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/di/OnboardingModuleTest.kt b/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/di/OnboardingModuleTest.kt
index 2840712..c85e18b 100644
--- a/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/di/OnboardingModuleTest.kt
+++ b/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/di/OnboardingModuleTest.kt
@@ -43,4 +43,4 @@ class OnboardingModuleTest {
)
)
}
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/domain/CheckUserPreferencesExistUseCaseTest.kt b/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/domain/CheckUserPreferencesExistUseCaseTest.kt
index 2af1688..6daa53d 100644
--- a/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/domain/CheckUserPreferencesExistUseCaseTest.kt
+++ b/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/domain/CheckUserPreferencesExistUseCaseTest.kt
@@ -75,4 +75,4 @@ class CheckUserPreferencesExistUseCaseTest {
// Then
assertThat(result).isFalse()
}
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/domain/SaveInitialUserPreferencesUseCaseTest.kt b/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/domain/SaveInitialUserPreferencesUseCaseTest.kt
index cc11840..63ddf94 100644
--- a/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/domain/SaveInitialUserPreferencesUseCaseTest.kt
+++ b/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/domain/SaveInitialUserPreferencesUseCaseTest.kt
@@ -98,4 +98,4 @@ class SaveInitialUserPreferencesUseCaseTest {
)
)
}
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/presentation/PreferencesViewModelTest.kt b/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/presentation/PreferencesViewModelTest.kt
index bed7a1f..6f92927 100644
--- a/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/presentation/PreferencesViewModelTest.kt
+++ b/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/presentation/PreferencesViewModelTest.kt
@@ -186,4 +186,4 @@ class PreferencesViewModelTest {
)
assertThat(collectedEvents).containsExactly(PreferencesEvent.Error(expectedErrorMessage))
}
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/presentation/UserVolumeUnitMapperTest.kt b/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/presentation/UserVolumeUnitMapperTest.kt
index 5bd0675..a3dd88d 100644
--- a/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/presentation/UserVolumeUnitMapperTest.kt
+++ b/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/presentation/UserVolumeUnitMapperTest.kt
@@ -60,4 +60,4 @@ class UserVolumeUnitMapperTest {
// Then
assertThat(unitLabelRes).isEqualTo(expectedLabelRes)
}
-}
\ No newline at end of file
+}
diff --git a/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/presentation/WelcomeViewModelTest.kt b/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/presentation/WelcomeViewModelTest.kt
index 0d77bdf..375ad40 100644
--- a/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/presentation/WelcomeViewModelTest.kt
+++ b/onboarding/src/test/kotlin/net/opatry/h2go/onboarding/presentation/WelcomeViewModelTest.kt
@@ -73,4 +73,4 @@ class WelcomeViewModelTest {
advanceUntilIdle()
assertThat(viewModel.uiState.value).isEqualTo(WelcomeUiState.ShowWelcome)
}
-}
\ No newline at end of file
+}
diff --git a/preferences/src/main/kotlin/net/opatry/h2go/preference/data/UserPreferencesDao.kt b/preferences/src/main/kotlin/net/opatry/h2go/preference/data/UserPreferencesDao.kt
index 7bfaceb..fe10121 100644
--- a/preferences/src/main/kotlin/net/opatry/h2go/preference/data/UserPreferencesDao.kt
+++ b/preferences/src/main/kotlin/net/opatry/h2go/preference/data/UserPreferencesDao.kt
@@ -46,4 +46,4 @@ interface UserPreferencesDao {
clear()
return upsert(defaultPreferences)
}
-}
\ No newline at end of file
+}
diff --git a/preferences/src/main/kotlin/net/opatry/h2go/preference/data/UserPreferencesMapper.kt b/preferences/src/main/kotlin/net/opatry/h2go/preference/data/UserPreferencesMapper.kt
index 652b28e..4c74ae0 100644
--- a/preferences/src/main/kotlin/net/opatry/h2go/preference/data/UserPreferencesMapper.kt
+++ b/preferences/src/main/kotlin/net/opatry/h2go/preference/data/UserPreferencesMapper.kt
@@ -44,4 +44,4 @@ class UserPreferencesMapper {
areNotificationsEnabled = preferences.areNotificationsEnabled,
notificationFrequencyInHours = preferences.notificationsFrequency.inWholeHours.toInt(),
)
-}
\ No newline at end of file
+}
diff --git a/preferences/src/main/kotlin/net/opatry/h2go/preference/data/UserPreferencesRepositoryImpl.kt b/preferences/src/main/kotlin/net/opatry/h2go/preference/data/UserPreferencesRepositoryImpl.kt
index f9c1a13..2a31e31 100644
--- a/preferences/src/main/kotlin/net/opatry/h2go/preference/data/UserPreferencesRepositoryImpl.kt
+++ b/preferences/src/main/kotlin/net/opatry/h2go/preference/data/UserPreferencesRepositoryImpl.kt
@@ -47,4 +47,4 @@ class UserPreferencesRepositoryImpl(
override suspend fun resetUserPreferences(defaultValue: UserPreferences) {
dao.reset(mapper.toEntity(defaultValue))
}
-}
\ No newline at end of file
+}
diff --git a/preferences/src/main/kotlin/net/opatry/h2go/preference/data/entity/UserPreferencesEntity.kt b/preferences/src/main/kotlin/net/opatry/h2go/preference/data/entity/UserPreferencesEntity.kt
index e95d487..0df0011 100644
--- a/preferences/src/main/kotlin/net/opatry/h2go/preference/data/entity/UserPreferencesEntity.kt
+++ b/preferences/src/main/kotlin/net/opatry/h2go/preference/data/entity/UserPreferencesEntity.kt
@@ -33,4 +33,4 @@ data class UserPreferencesEntity(
val volumeUnit: String,
val areNotificationsEnabled: Boolean,
val notificationFrequencyInHours: Int,
-)
\ No newline at end of file
+)
diff --git a/preferences/src/main/kotlin/net/opatry/h2go/preference/di/preferencesModule.kt b/preferences/src/main/kotlin/net/opatry/h2go/preference/di/preferencesModule.kt
index 47b51b7..2e61a18 100644
--- a/preferences/src/main/kotlin/net/opatry/h2go/preference/di/preferencesModule.kt
+++ b/preferences/src/main/kotlin/net/opatry/h2go/preference/di/preferencesModule.kt
@@ -35,4 +35,4 @@ val preferencesModule = module {
singleOf(::UserPreferencesRepositoryImpl) bind UserPreferencesRepository::class
-}
\ No newline at end of file
+}
diff --git a/preferences/src/main/kotlin/net/opatry/h2go/preference/domain/UserPreferencesRepository.kt b/preferences/src/main/kotlin/net/opatry/h2go/preference/domain/UserPreferencesRepository.kt
index ede5214..dba83a8 100644
--- a/preferences/src/main/kotlin/net/opatry/h2go/preference/domain/UserPreferencesRepository.kt
+++ b/preferences/src/main/kotlin/net/opatry/h2go/preference/domain/UserPreferencesRepository.kt
@@ -30,4 +30,4 @@ interface UserPreferencesRepository {
suspend fun updateUserPreferences(preferences: UserPreferences)
suspend fun resetUserPreferences(defaultValue: UserPreferences)
-}
\ No newline at end of file
+}
diff --git a/preferences/src/main/kotlin/net/opatry/h2go/preference/domain/VolumeUnit.kt b/preferences/src/main/kotlin/net/opatry/h2go/preference/domain/VolumeUnit.kt
index fb8ff80..e29fbb3 100644
--- a/preferences/src/main/kotlin/net/opatry/h2go/preference/domain/VolumeUnit.kt
+++ b/preferences/src/main/kotlin/net/opatry/h2go/preference/domain/VolumeUnit.kt
@@ -25,4 +25,4 @@ package net.opatry.h2go.preference.domain
enum class VolumeUnit {
Milliliter,
Oz,
-}
\ No newline at end of file
+}
diff --git a/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesDaoTest.kt b/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesDaoTest.kt
index 0299359..7cf66fa 100644
--- a/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesDaoTest.kt
+++ b/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesDaoTest.kt
@@ -165,4 +165,4 @@ class UserPreferencesDaoTest {
val resultingPreferences = dao.getUserPreferences().first()
assertThat(resultingPreferences).isEqualTo(defaultPreferences)
}
-}
\ No newline at end of file
+}
diff --git a/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesMapperTest.kt b/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesMapperTest.kt
index b8609df..a984d7a 100644
--- a/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesMapperTest.kt
+++ b/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesMapperTest.kt
@@ -100,4 +100,4 @@ class UserPreferencesMapperTest {
assertThat(result.areNotificationsEnabled).isEqualTo(areNotificationsEnabled)
assertThat(result.notificationFrequencyInHours).isEqualTo(3)
}
-}
\ No newline at end of file
+}
diff --git a/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesRepositoryTest.kt b/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesRepositoryTest.kt
index 56bd64f..0ec959b 100644
--- a/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesRepositoryTest.kt
+++ b/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesRepositoryTest.kt
@@ -133,4 +133,4 @@ class UserPreferencesRepositoryTest {
val resultingPreferences = repository.getUserPreferences().first()
assertThat(resultingPreferences).isEqualTo(defaultPreferences)
}
-}
\ No newline at end of file
+}
diff --git a/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesTestDatabase.kt b/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesTestDatabase.kt
index 3d69da9..68b1369 100644
--- a/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesTestDatabase.kt
+++ b/preferences/src/test/kotlin/net/opatry/h2go/preference/data/UserPreferencesTestDatabase.kt
@@ -29,4 +29,4 @@ import net.opatry.h2go.preference.data.entity.UserPreferencesEntity
@Database(entities = [UserPreferencesEntity::class], version = 1, exportSchema = false)
abstract class UserPreferencesTestDatabase : RoomDatabase() {
abstract fun userPreferencesDao(): UserPreferencesDao
-}
\ No newline at end of file
+}
diff --git a/preferences/src/test/kotlin/net/opatry/h2go/preference/di/PreferencesModuleTest.kt b/preferences/src/test/kotlin/net/opatry/h2go/preference/di/PreferencesModuleTest.kt
index 7e7efaa..b190583 100644
--- a/preferences/src/test/kotlin/net/opatry/h2go/preference/di/PreferencesModuleTest.kt
+++ b/preferences/src/test/kotlin/net/opatry/h2go/preference/di/PreferencesModuleTest.kt
@@ -41,4 +41,4 @@ class PreferencesModuleTest {
)
)
}
-}
\ No newline at end of file
+}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index f89e5eb..cf055f6 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -42,8 +42,9 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
rootProject.name = "H2Go"
+include(":detekt-rules")
include(":h2go-app")
-include(":preferences")
+include(":preferences")
include(":onboarding")
include(":android-test-util")
include(":test-util")
diff --git a/test-util/build.gradle.kts b/test-util/build.gradle.kts
index 47b198a..27947c9 100644
--- a/test-util/build.gradle.kts
+++ b/test-util/build.gradle.kts
@@ -21,7 +21,7 @@
*/
plugins {
- id("kotlin")
+ kotlin("jvm")
}
kotlin {
diff --git a/test-util/src/main/kotlin/net/opatry/test/util/MainDispatcherExtension.kt b/test-util/src/main/kotlin/net/opatry/test/util/MainDispatcherExtension.kt
index ede819f..0b97629 100644
--- a/test-util/src/main/kotlin/net/opatry/test/util/MainDispatcherExtension.kt
+++ b/test-util/src/main/kotlin/net/opatry/test/util/MainDispatcherExtension.kt
@@ -11,10 +11,12 @@ import org.junit.jupiter.api.extension.ExtensionContext
@ExperimentalCoroutinesApi
class MainDispatcherExtension : BeforeAllCallback, AfterAllCallback {
+
override fun beforeAll(context: ExtensionContext?) {
Dispatchers.setMain(StandardTestDispatcher())
}
+
override fun afterAll(context: ExtensionContext?) {
Dispatchers.resetMain()
}
-}
\ No newline at end of file
+}