diff --git a/build.gradle.kts b/build.gradle.kts index e6280ec..17badb2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2026, OpenSavvy and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension @@ -31,7 +47,6 @@ dependencies { library(projects.runners.runnerTestInitiative) library(projects.runners.runnerTestballoon) library(projects.compat.compatGradle) - library(projects.compat.compatKotlinxDatetime) library(projects.compat.compatJavaTime) library(projects.compat.compatFilesystem) library(projects.compat.compatArrow) diff --git a/compat/compat-kotlinx-datetime/README.md b/compat/compat-kotlinx-datetime/README.md deleted file mode 100644 index ce3fa2f..0000000 --- a/compat/compat-kotlinx-datetime/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# Module Compatibility with KotlinX.Datetime (DEPRECATED) - -Control the virtual time during tests using KotlinX.Datetime. - - - -Builds upon the [virtual time control][opensavvy.prepared.suite.time] available out-of-the-box to allow -[instancing clocks][opensavvy.prepared.compat.kotlinx.datetime.clock], [setting the current time][opensavvy.prepared.compat.kotlinx.datetime.set] or [waiting for a given time][opensavvy.prepared.compat.kotlinx.datetime.delayUntil]. - -## Deprecation notice - -This module is built on top of the KotlinX.Datetime support for `Instant` and `Clock`, which have been removed in KotlinX.Datetime 0.7.0. - -`Instant` and `Clock` have been moved to the Kotlin standard library. The contents of this compatibility module have therefore been integrated into the main Prepared module, Prepared Suite. - -All functionality provided by this module is available in Prepared Suite, with a different package name. - -This module will not be updated in the future. - -## Example - -We want to test a fictional `Scheduler` implemented using [KotlinX.Coroutines](https://kotlinlang.org/docs/coroutines-guide.html). -The scheduler has been implemented in a way that allows to inject the clock and the coroutine context. - -First, the scheduler requires access to some kind of database. -We [prepare][opensavvy.prepared.suite.prepared] the connection to avoid copy-pasting it in each test, while still -ensuring each test gets its own instance. - -```kotlin -val prepareDatabase by prepared { - Database.connect() -} -``` - -To allow writing multiple tests using the same scheduler, we also declare it as a prepared value. -We can inject the database using the previous prepared value. -To let the scheduler access the virtual time, we inject the [virtual time clock][opensavvy.prepared.compat.kotlinx.datetime.clock]. -To ensure the scheduler can start coroutines with delay-skipping that the test waits for, we inject the [foreground coroutine scope][opensavvy.prepared.suite.foregroundScope]. - -```kotlin -val prepareScheduler by prepared { - Scheduler( - database = prepareDatabase(), - clock = time.clock, - coroutineContext = foregroundScope, - ) -} -``` - -Now, we can use the helper functions [to set the current time][opensavvy.prepared.compat.kotlinx.datetime.set] -and to [wait until a specific time][opensavvy.prepared.compat.kotlinx.datetime.delayUntil]. - -```kotlin -test("A test that uses the time") { - time.set("2023-11-08T12:00:00Z") - - val scheduler = prepareScheduler() - - var executed = false - scheduler.scheduleAt("2023-11-08T12:05:00Z") { - executed = true - } - - time.delayUntil("2023-11-08T12:06:00Z") - executed shouldBe true -} -``` diff --git a/compat/compat-kotlinx-datetime/build.gradle.kts b/compat/compat-kotlinx-datetime/build.gradle.kts deleted file mode 100644 index 2f4708c..0000000 --- a/compat/compat-kotlinx-datetime/build.gradle.kts +++ /dev/null @@ -1,66 +0,0 @@ -import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl - -plugins { - alias(opensavvyConventions.plugins.base) - alias(opensavvyConventions.plugins.kotlin.library) - alias(libs.plugins.testBalloon) -} - -@OptIn(ExperimentalWasmDsl::class) -kotlin { - jvm() - js { - browser() - nodejs() - } - linuxX64() - linuxArm64() - macosX64() - macosArm64() - iosArm64() - iosX64() - iosSimulatorArm64() - watchosX64() - watchosArm32() - watchosArm64() - watchosSimulatorArm64() - tvosX64() - tvosArm64() - tvosSimulatorArm64() - mingwX64() - wasmJs { - browser() - nodejs() - } - wasmWasi { - nodejs() - } - - sourceSets.commonMain { - dependencies { - api(projects.suite) - api(libs.kotlinx.datetime) - } - } - - sourceSets.commonTest { - dependencies { - implementation(projects.runners.runnerTestballoon) - } - } -} - -library { - name.set("Compatibility with KotlinX.Datetime (DEPRECATED)") - description.set("Control the passing of time in Prepared tests using objects and methods from KotlinX.Datetime, including Clock and Instant") - homeUrl.set("https://prepared.opensavvy.dev/features/time.html") - - license.set { - name.set("Apache 2.0") - url.set("https://www.apache.org/licenses/LICENSE-2.0.txt") - } -} - -kotlin { - jvmToolchain(11) -} diff --git a/compat/compat-kotlinx-datetime/src/commonMain/kotlin/KotlinTime.kt b/compat/compat-kotlinx-datetime/src/commonMain/kotlin/KotlinTime.kt deleted file mode 100644 index 397e0e3..0000000 --- a/compat/compat-kotlinx-datetime/src/commonMain/kotlin/KotlinTime.kt +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2023-2025, OpenSavvy and contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package opensavvy.prepared.compat.kotlinx.datetime - -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.delay -import kotlinx.coroutines.test.TestCoroutineScheduler -import kotlinx.datetime.Clock -import kotlinx.datetime.Instant -import opensavvy.prepared.suite.Time -import opensavvy.prepared.suite.nowMillis - -@ExperimentalCoroutinesApi -private class KotlinClock(private val scheduler: TestCoroutineScheduler) : Clock { - override fun now(): Instant = - Instant.fromEpochMilliseconds(scheduler.currentTime) -} - -/** - * Creates a [Clock] that follows the virtual time in this test. - * - * ### Example - * - * ```kotlin - * test("Pass the time to an external service") { - * val service = SomeExternalService(time.clock) - * } - * ``` - * - * @see now Access the current time - * @see set Set the current time - */ -@ExperimentalCoroutinesApi -val Time.clock: Clock - get() = KotlinClock(scheduler) - -/** - * Accesses the current virtual time within this test, as an [Instant]. - * - * ### Example - * - * ```kotlin - * test("Access the current time") { - * println(time.now) - * } - * ``` - * - * @see clock Pass a way to access the time to another system - */ -@ExperimentalCoroutinesApi -val Time.now: Instant - get() = clock.now() - -/** - * Advances the virtual time until it reaches [instant]. - * - * ### Comparison with delayUntil - * - * This function is identical in behavior to [delayUntil]. - * It exists because tests often read better when using it to set the initial date: - * ```kotlin - * test("Some test") { - * // Given: - * time.set(Instant.parse("2024-02-13T21:32:41Z")) - * - * // When: - * // … - * delayUntil(Instant.parse("2024-02-13T21:35:01Z")) - * // … - * - * // Then: - * // … - * } - * ``` - * - * We recommend using [set] to set the initial date at the very start of a test, and using [delayUntil] inside the test - * logic. - * - * It is not possible to set the time to a date in the past. - */ -@ExperimentalCoroutinesApi -suspend fun Time.set(instant: Instant) { - delayUntil(instant) -} - -/** - * Advances the virtual time until it reaches [isoString], formatted as an ISO 8601 timestamp. - * - * It is not possible to set the time to a date in the past. - * - * ### Example - * - * ```kotlin - * test("Everything should behave the same on December 31st") { - * time.set("2022-12-31T23:37:00Z") - * - * // … - * } - * ``` - * - * ### Comparison with delayUntil - * - * This function is identical in behavior to [delayUntil]. - * It exists because tests often read better when using it to set the initial date: - * ```kotlin - * test("Some test") { - * // Given: - * time.set("2024-02-13T21:32:41Z") - * - * // When: - * // … - * delayUntil("2024-02-13T21:35:01Z") - * // … - * - * // Then: - * // … - * } - * ``` - * - * We recommend using [set] to set the initial date at the very start of a test, and using [delayUntil] inside the test - * logic. - * - * @see now Access the current time - * @see delay Wait for some duration - * @see delayUntil Wait for a specific time - */ -@ExperimentalCoroutinesApi -suspend fun Time.set(isoString: String) { - set(Instant.parse(isoString)) -} - -/** - * Delays until the virtual time reaches [instant], executing all enqueued tasks in order. - * - * `delayUntil` is useful to artificially trigger time-dependent algorithms. - * To set the initial time at the start of the test, use [set]. - */ -@ExperimentalCoroutinesApi -suspend fun Time.delayUntil(instant: Instant) { - val diff = instant.toEpochMilliseconds() - nowMillis - require(diff >= 0) { "Cannot delay until $instant, which is in the past of the current virtual time, $now" } - delay(diff) -} - -/** - * Delays until the virtual time reaches [isoString], formatted as an ISO 8601 timestamp, executing all enqueued tasks in order. - * - * `delayUntil` is useful to artificially trigger time-dependent algorithms. - * To set the initial time at the start of the test, use [set]. - * - * @see set Set the current time - * @see now Access the current time - */ -@ExperimentalCoroutinesApi -suspend fun Time.delayUntil(isoString: String) { - delayUntil(Instant.parse(isoString)) -} diff --git a/docs/website/build.gradle.kts b/docs/website/build.gradle.kts index eb6af93..96c18e5 100644 --- a/docs/website/build.gradle.kts +++ b/docs/website/build.gradle.kts @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2026, OpenSavvy and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + plugins { alias(opensavvyConventions.plugins.base) id("dev.opensavvy.dokka-mkdocs") @@ -11,7 +27,6 @@ dependencies { dokka(projects.runners.runnerTestInitiative) dokka(projects.runners.runnerTestballoon) dokka(projects.compat.compatGradle) - dokka(projects.compat.compatKotlinxDatetime) dokka(projects.compat.compatJavaTime) dokka(projects.compat.compatFilesystem) dokka(projects.compat.compatArrow) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fd38416..3f26d3c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,6 @@ [versions] arrow = "2.1.2" # https://github.com/arrow-kt/arrow/releases kotlinx-coroutines = "1.10.2" # https://github.com/Kotlin/kotlinx.coroutines/releases -kotlinx-datetime = "0.6.2" # https://github.com/Kotlin/kotlinx-datetime/releases gradle-testkit = "8.11.1" # https://gradle.org/releases/ parameterize = "0.4.0" # https://github.com/BenWoodworth/Parameterize/releases ktor = "3.1.3" # https://ktor.io/docs/releases.html#release-details @@ -19,7 +18,6 @@ kotest = { id = "io.kotest", version.ref = "kotest" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } kotlinx-coroutines-debug = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-debug", version.ref = "kotlinx-coroutines" } kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" } -kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" } gradle-testkit = { module = "dev.gradleplugins:gradle-test-kit", version.ref = "gradle-testkit" } arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" } parameterize = { module = "com.benwoodworth.parameterize:parameterize", version.ref = "parameterize" } diff --git a/runners/runner-kotlin-test/build.gradle.kts b/runners/runner-kotlin-test/build.gradle.kts index 1fc9879..08c6171 100644 --- a/runners/runner-kotlin-test/build.gradle.kts +++ b/runners/runner-kotlin-test/build.gradle.kts @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2026, OpenSavvy and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + plugins { alias(opensavvyConventions.plugins.base) alias(opensavvyConventions.plugins.kotlin.library) @@ -30,12 +46,6 @@ kotlin { } } - sourceSets.commonTest { - dependencies { - implementation(projects.compat.compatKotlinxDatetime) - } - } - sourceSets.jvmMain { dependencies { api(libsCommon.kotlin.test.junit5) diff --git a/runners/runner-kotlin-test/src/commonTest/kotlin/TimeTest.kt b/runners/runner-kotlin-test/src/commonTest/kotlin/TimeTest.kt index ab1c1bc..b176fce 100644 --- a/runners/runner-kotlin-test/src/commonTest/kotlin/TimeTest.kt +++ b/runners/runner-kotlin-test/src/commonTest/kotlin/TimeTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2025, OpenSavvy and contributors. + * Copyright (c) 2023-2026, OpenSavvy and contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,8 +19,6 @@ package opensavvy.prepared.runner.kotlin import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import opensavvy.prepared.compat.kotlinx.datetime.now -import opensavvy.prepared.compat.kotlinx.datetime.set import opensavvy.prepared.suite.* import kotlin.test.assertEquals import kotlin.time.ExperimentalTime diff --git a/settings.gradle.kts b/settings.gradle.kts index 5679e1e..ebc2cb7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2026, OpenSavvy and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /* * This file was generated by the Gradle 'init' task. * @@ -65,7 +81,6 @@ include( "suite", - "compat:compat-kotlinx-datetime", "compat:compat-java-time", "compat:compat-gradle", "compat:compat-filesystem",