From 36fad2491e6785082b01ff66ccae7a811cd36fc9 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Wed, 8 Apr 2026 07:24:28 -0500 Subject: [PATCH] Remove runBlocking from common source sets and update coroutines for KMP --- gradle/libs.versions.toml | 3 +-- uhabits-core/build.gradle.kts | 5 ++-- .../kotlin/org/isoron/platform/RunSuspend.kt | 21 +++++++++++++++++ .../uhabits/core/tasks/ExportCSVTask.kt | 6 ++--- .../org/isoron/platform/io/MigrationTest.kt | 4 ++-- .../org/isoron/uhabits/core/BaseUnitTest.kt | 8 +++---- .../core/database/migrations/Version22Test.kt | 4 ++-- .../core/database/migrations/Version23Test.kt | 4 ++-- .../uhabits/core/io/HabitsCSVExporterTest.kt | 4 ++-- .../org/isoron/uhabits/core/io/ImportTest.kt | 4 ++-- .../habits/list/ListHabitsBehaviorTest.kt | 4 ++-- .../habits/show/ShowHabitMenuPresenterTest.kt | 4 ++-- .../uhabits/core/ui/views/BarChartTest.kt | 10 ++++---- .../uhabits/core/ui/views/HistoryChartTest.kt | 18 +++++++-------- .../uhabits/core/utils/FileExtensionsTest.kt | 4 ++-- .../java/org/isoron/platform/JvmRunSuspend.kt | 23 +++++++++++++++++++ .../uhabits/core/utils/MidnightTimerTest.kt | 1 - 17 files changed, 85 insertions(+), 42 deletions(-) create mode 100644 uhabits-core/src/commonMain/kotlin/org/isoron/platform/RunSuspend.kt create mode 100644 uhabits-core/src/jvmMain/java/org/isoron/platform/JvmRunSuspend.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6a4448ca..641f0bc0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,7 +17,6 @@ junitJupiter = "5.10.1" junitVersion = "4.13.2" konfetti-xml = "2.0.2" kotlin = "2.1.10" -kotlinxCoroutinesCoreCommon = "1.3.8" ksp = "2.1.10-1.0.30" ktlint-plugin = "11.6.1" ktor = "1.6.8" @@ -54,8 +53,8 @@ konfetti-xml = { group = "nl.dionsegijn", name = "konfetti-xml", version.ref = " kotlin-stdlib-jdk8 = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" } kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "ktxCoroutine" } kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "ktxCoroutine" } -kotlinx-coroutines-core-common = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core-common", version.ref = "kotlinxCoroutinesCoreCommon" } kotlinx-coroutines-core-jvm = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", version.ref = "ktxCoroutine" } +kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "ktxCoroutine" } ktor-client-android = { group = "io.ktor", name = "ktor-client-android", version.ref = "ktor" } ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" } ktor-client-jackson = { group = "io.ktor", name = "ktor-client-jackson", version.ref = "ktor" } diff --git a/uhabits-core/build.gradle.kts b/uhabits-core/build.gradle.kts index 350283bc..3f05a9ee 100644 --- a/uhabits-core/build.gradle.kts +++ b/uhabits-core/build.gradle.kts @@ -31,7 +31,8 @@ kotlin { val commonMain by getting { dependencies { implementation(kotlin("stdlib-common")) - implementation(libs.kotlinx.coroutines.core.common) + implementation(libs.kotlinx.coroutines.core) + compileOnly(libs.kotlin.inject.runtime) } } @@ -39,13 +40,13 @@ kotlin { dependencies { implementation(kotlin("test-common")) implementation(kotlin("test-annotations-common")) + implementation(libs.kotlinx.coroutines.test) } } val jvmMain by getting { dependencies { implementation(kotlin("stdlib-jdk8")) - compileOnly(libs.kotlin.inject.runtime) implementation(libs.guava) implementation(libs.kotlinx.coroutines.core.jvm) implementation(libs.annotation) diff --git a/uhabits-core/src/commonMain/kotlin/org/isoron/platform/RunSuspend.kt b/uhabits-core/src/commonMain/kotlin/org/isoron/platform/RunSuspend.kt new file mode 100644 index 00000000..416ef821 --- /dev/null +++ b/uhabits-core/src/commonMain/kotlin/org/isoron/platform/RunSuspend.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2016-2025 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +package org.isoron.platform + +expect fun runSuspend(block: suspend () -> T): T diff --git a/uhabits-core/src/commonMain/kotlin/org/isoron/uhabits/core/tasks/ExportCSVTask.kt b/uhabits-core/src/commonMain/kotlin/org/isoron/uhabits/core/tasks/ExportCSVTask.kt index 0cb804de..76c0559c 100644 --- a/uhabits-core/src/commonMain/kotlin/org/isoron/uhabits/core/tasks/ExportCSVTask.kt +++ b/uhabits-core/src/commonMain/kotlin/org/isoron/uhabits/core/tasks/ExportCSVTask.kt @@ -18,8 +18,8 @@ */ package org.isoron.uhabits.core.tasks -import kotlinx.coroutines.runBlocking import org.isoron.platform.io.UserFile +import org.isoron.platform.runSuspend import org.isoron.platform.time.getToday import org.isoron.uhabits.core.io.HabitsCSVExporter import org.isoron.uhabits.core.models.Habit @@ -35,10 +35,10 @@ class ExportCSVTask( override fun doInBackground() { try { val exporter = HabitsCSVExporter(habitList, selectedHabits) - val bytes = runBlocking { exporter.writeArchive() } + val bytes = runSuspend { exporter.writeArchive() } val date = getToday().toCSVString() val zipFile = outputDir.resolve("Loop Habits CSV $date.zip") - runBlocking { zipFile.writeBytes(bytes) } + runSuspend { zipFile.writeBytes(bytes) } archiveFilename = zipFile.pathString } catch (e: Exception) { e.printStackTrace() diff --git a/uhabits-core/src/commonTest/kotlin/org/isoron/platform/io/MigrationTest.kt b/uhabits-core/src/commonTest/kotlin/org/isoron/platform/io/MigrationTest.kt index 820cdc56..d5395188 100644 --- a/uhabits-core/src/commonTest/kotlin/org/isoron/platform/io/MigrationTest.kt +++ b/uhabits-core/src/commonTest/kotlin/org/isoron/platform/io/MigrationTest.kt @@ -1,6 +1,6 @@ package org.isoron.platform.io -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runTest import kotlin.test.Test import kotlin.test.assertEquals @@ -32,7 +32,7 @@ class MigrationTest { } @Test - fun testMigrateIdempotent() = runBlocking { + fun testMigrateIdempotent() = runTest { val db = TestDatabaseHelper.createEmptyDatabase() val version = db.getVersion() db.migrateTo(version) { v -> TestDatabaseHelper.loadMigrationSQL(v) } diff --git a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/BaseUnitTest.kt b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/BaseUnitTest.kt index cd132eb0..e14e224e 100644 --- a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/BaseUnitTest.kt +++ b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/BaseUnitTest.kt @@ -18,7 +18,6 @@ */ package org.isoron.uhabits.core -import kotlinx.coroutines.runBlocking import org.isoron.platform.io.Database import org.isoron.platform.io.DatabaseOpener import org.isoron.platform.io.FileOpener @@ -26,6 +25,7 @@ import org.isoron.platform.io.TestDatabaseHelper import org.isoron.platform.io.UserFile import org.isoron.platform.io.createTestDatabaseOpener import org.isoron.platform.io.createTestFileOpener +import org.isoron.platform.runSuspend import org.isoron.platform.time.LocalDate import org.isoron.platform.time.setToday import org.isoron.uhabits.core.commands.CommandRunner @@ -56,20 +56,20 @@ open class BaseUnitTest { commandRunner = CommandRunner(taskRunner) } - protected fun createTempDir(): UserFile = runBlocking { + protected fun createTempDir(): UserFile = runSuspend { val dir = fileOpener.openUserFile("test-temp-dir-${tempFileCounter++}") dir.mkdirs() dir } - protected fun copyResourceToTempFile(resourcePath: String): UserFile = runBlocking { + protected fun copyResourceToTempFile(resourcePath: String): UserFile = runSuspend { val cleanPath = resourcePath.removePrefix("/") val tempFile = fileOpener.openUserFile("test-temp-${tempFileCounter++}") fileOpener.openResourceFile(cleanPath).copyTo(tempFile) tempFile } - protected fun openDatabaseResource(resourcePath: String): Database = runBlocking { + protected fun openDatabaseResource(resourcePath: String): Database = runSuspend { val tempFile = copyResourceToTempFile(resourcePath) databaseOpener.open(tempFile.pathString) } diff --git a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/database/migrations/Version22Test.kt b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/database/migrations/Version22Test.kt index 45ceb759..9cff1ecf 100644 --- a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/database/migrations/Version22Test.kt +++ b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/database/migrations/Version22Test.kt @@ -18,11 +18,11 @@ */ package org.isoron.uhabits.core.database.migrations -import kotlinx.coroutines.runBlocking import org.isoron.platform.io.Database import org.isoron.platform.io.migrateTo import org.isoron.platform.io.querySingle import org.isoron.platform.io.run +import org.isoron.platform.runSuspend import org.isoron.uhabits.core.BaseUnitTest import kotlin.test.Test import kotlin.test.assertContains @@ -37,7 +37,7 @@ class Version22Test : BaseUnitTest() { db = openDatabaseResource("/databases/021.db") } - private fun migrateTo(version: Int) = runBlocking { + private fun migrateTo(version: Int) = runSuspend { db.migrateTo(version) { v -> val path = "migrations/%02d.sql".format(v) fileOpener.openResourceFile(path).lines().joinToString("\n") diff --git a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/database/migrations/Version23Test.kt b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/database/migrations/Version23Test.kt index a02b8126..24fa0ffb 100644 --- a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/database/migrations/Version23Test.kt +++ b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/database/migrations/Version23Test.kt @@ -19,10 +19,10 @@ package org.isoron.uhabits.core.database.migrations -import kotlinx.coroutines.runBlocking import org.isoron.platform.io.Database import org.isoron.platform.io.migrateTo import org.isoron.platform.io.query +import org.isoron.platform.runSuspend import org.isoron.uhabits.core.BaseUnitTest import kotlin.test.Test import kotlin.test.assertEquals @@ -36,7 +36,7 @@ class Version23Test : BaseUnitTest() { db = openDatabaseResource("/databases/022.db") } - private fun migrateTo(version: Int) = runBlocking { + private fun migrateTo(version: Int) = runSuspend { db.migrateTo(version) { v -> val path = "migrations/%02d.sql".format(v) fileOpener.openResourceFile(path).lines().joinToString("\n") diff --git a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/io/HabitsCSVExporterTest.kt b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/io/HabitsCSVExporterTest.kt index 42a7a90c..ac899873 100644 --- a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/io/HabitsCSVExporterTest.kt +++ b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/io/HabitsCSVExporterTest.kt @@ -18,7 +18,7 @@ */ package org.isoron.uhabits.core.io -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runTest import org.isoron.platform.io.ZipReader import org.isoron.uhabits.core.BaseUnitTest import org.isoron.uhabits.core.models.Habit @@ -36,7 +36,7 @@ class HabitsCSVExporterTest : BaseUnitTest() { } @Test - fun testExportCSV() = runBlocking { + fun testExportCSV() = runTest { val selected: MutableList = mutableListOf() for (h in habitList) selected.add(h) val exporter = HabitsCSVExporter(habitList, selected) diff --git a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/io/ImportTest.kt b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/io/ImportTest.kt index 5aaff525..b2b69b68 100644 --- a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/io/ImportTest.kt +++ b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/io/ImportTest.kt @@ -18,7 +18,7 @@ */ package org.isoron.uhabits.core.io -import kotlinx.coroutines.runBlocking +import org.isoron.platform.runSuspend import org.isoron.platform.time.LocalDate import org.isoron.uhabits.core.BaseUnitTest import org.isoron.uhabits.core.models.Entry @@ -157,7 +157,7 @@ class ImportTest : BaseUnitTest() { return h.originalEntries.get(LocalDate(year, month, day)).notes == notes } - private fun importFromFile(assetFilename: String) = runBlocking { + private fun importFromFile(assetFilename: String) = runSuspend { val userFile = copyResourceToTempFile(assetFilename) assertTrue(userFile.exists()) val importer = GenericImporter( diff --git a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt index 408d6c37..5dea98b2 100644 --- a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt +++ b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt @@ -26,8 +26,8 @@ import dev.mokkery.matcher.any import dev.mokkery.mock import dev.mokkery.spy import dev.mokkery.verify -import kotlinx.coroutines.runBlocking import org.isoron.platform.io.UserFile +import org.isoron.platform.runSuspend import org.isoron.platform.time.getToday import org.isoron.uhabits.core.BaseUnitTest import org.isoron.uhabits.core.models.Entry @@ -94,7 +94,7 @@ class ListHabitsBehaviorTest : BaseUnitTest() { every { dirFinder.getCSVOutputDir() } returns outputDir behavior.onExportCSV() verify { screen.showSendFileScreen(any()) } - val files = runBlocking { outputDir.listFiles() } + val files = runSuspend { outputDir.listFiles() } assertEquals(1, files!!.size) } diff --git a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitMenuPresenterTest.kt b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitMenuPresenterTest.kt index 87087e0a..7fe136fe 100644 --- a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitMenuPresenterTest.kt +++ b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitMenuPresenterTest.kt @@ -22,7 +22,7 @@ import dev.mokkery.answering.returns import dev.mokkery.every import dev.mokkery.mock import dev.mokkery.verify -import kotlinx.coroutines.runBlocking +import org.isoron.platform.runSuspend import org.isoron.uhabits.core.BaseUnitTest import org.isoron.uhabits.core.models.Habit import kotlin.test.Test @@ -60,7 +60,7 @@ class ShowHabitMenuPresenterTest : BaseUnitTest() { val outputDir = createTempDir() every { system.getCSVOutputDir() } returns outputDir menu.onExportCSV() - val files = runBlocking { outputDir.listFiles() } + val files = runSuspend { outputDir.listFiles() } assertEquals(1, files!!.size) } } diff --git a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/views/BarChartTest.kt b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/views/BarChartTest.kt index a952c319..91181905 100644 --- a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/views/BarChartTest.kt +++ b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/views/BarChartTest.kt @@ -19,7 +19,7 @@ package org.isoron.uhabits.core.ui.views -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runTest import org.isoron.platform.gui.assertRenders import org.isoron.platform.io.createTestDateFormatter import org.isoron.platform.time.LocalDate @@ -41,24 +41,24 @@ class BarChartTest { } @Test - fun testDraw() = runBlocking { + fun testDraw() = runTest { assertRenders(300, 200, "$base/base.png", component) } @Test - fun testDrawDarkTheme() = runBlocking { + fun testDrawDarkTheme() = runTest { component.theme = DarkTheme() assertRenders(300, 200, "$base/themeDark.png", component) } @Test - fun testDrawWidgetTheme() = runBlocking { + fun testDrawWidgetTheme() = runTest { component.theme = WidgetTheme() assertRenders(300, 200, "$base/themeWidget.png", component) } @Test - fun testDrawWithOffset() = runBlocking { + fun testDrawWithOffset() = runTest { component.dataOffset = 5 assertRenders(300, 200, "$base/offset.png", component) } diff --git a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt index 6bcefeb8..2bdee8b5 100644 --- a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt +++ b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt @@ -23,7 +23,7 @@ import dev.mokkery.mock import dev.mokkery.resetCalls import dev.mokkery.verify import dev.mokkery.verifyNoMoreCalls -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runTest import org.isoron.platform.gui.assertRenders import org.isoron.platform.io.createTestDateFormatter import org.isoron.platform.time.DayOfWeek @@ -78,12 +78,12 @@ class HistoryChartTest { ) @Test - fun testDraw() = runBlocking { + fun testDraw() = runTest { assertRenders(400, 200, "$base/base.png", view) } @Test - fun testClick() = runBlocking { + fun testClick() = runTest { assertRenders(400, 200, "$base/base.png", view) // Click top left date @@ -114,7 +114,7 @@ class HistoryChartTest { } @Test - fun testLongClick() = runBlocking { + fun testLongClick() = runTest { assertRenders(400, 200, "$base/base.png", view) // Click top left date @@ -145,30 +145,30 @@ class HistoryChartTest { } @Test - fun testDrawWeekDay() = runBlocking { + fun testDrawWeekDay() = runTest { view.firstWeekday = DayOfWeek.MONDAY assertRenders(400, 200, "$base/weekday.png", view) } @Test - fun testDrawDifferentSize() = runBlocking { + fun testDrawDifferentSize() = runTest { assertRenders(200, 200, "$base/small.png", view) } @Test - fun testDrawDarkTheme() = runBlocking { + fun testDrawDarkTheme() = runTest { view.theme = DarkTheme() assertRenders(400, 200, "$base/themeDark.png", view) } @Test - fun testDrawWidgetTheme() = runBlocking { + fun testDrawWidgetTheme() = runTest { view.theme = WidgetTheme() assertRenders(400, 200, "$base/themeWidget.png", view) } @Test - fun testDrawOffset() = runBlocking { + fun testDrawOffset() = runTest { view.dataOffset = 2 assertRenders(400, 200, "$base/scroll.png", view) } diff --git a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/utils/FileExtensionsTest.kt b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/utils/FileExtensionsTest.kt index 2b3bc4b1..3fe78d41 100644 --- a/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/utils/FileExtensionsTest.kt +++ b/uhabits-core/src/commonTest/kotlin/org/isoron/uhabits/core/utils/FileExtensionsTest.kt @@ -1,6 +1,6 @@ package org.isoron.uhabits.core.utils -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runTest import org.isoron.uhabits.core.BaseUnitTest import kotlin.test.Test import kotlin.test.assertTrue @@ -8,7 +8,7 @@ import kotlin.test.assertTrue class FileExtensionsTest : BaseUnitTest() { @Test - fun testIsSQLite3File() = runBlocking { + fun testIsSQLite3File() = runTest { val userFile = copyResourceToTempFile("loop.db") val isSqlite3File = isSQLite3File(userFile) assertTrue(isSqlite3File) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/platform/JvmRunSuspend.kt b/uhabits-core/src/jvmMain/java/org/isoron/platform/JvmRunSuspend.kt new file mode 100644 index 00000000..a8ad2452 --- /dev/null +++ b/uhabits-core/src/jvmMain/java/org/isoron/platform/JvmRunSuspend.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016-2025 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +package org.isoron.platform + +import kotlinx.coroutines.runBlocking + +actual fun runSuspend(block: suspend () -> T): T = runBlocking { block() } diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt index 12b91887..15beef6c 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt @@ -57,5 +57,4 @@ class MidnightTimerTest : BaseUnitTest() { assertEquals(true, suspendedListener) } } - }