From d70577a960400b903fd3bef1d939acba052dc5b4 Mon Sep 17 00:00:00 2001 From: Ivan “CLOVIS” Canet Date: Fri, 31 Jul 2026 10:22:35 +0000 Subject: [PATCH] merge: Improve interoperability with the TestBalloon IntelliJ plugin See merge request opensavvy/groundwork/prepared!250 --- runners/runner-testballoon/src/commonMain/kotlin/Suite.kt | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file(s) changed, 86 insertion(s)(+), 5 deletion(s)(-) diff --git a/runners/runner-testballoon/src/commonMain/kotlin/Suite.kt b/runners/runner-testballoon/src/commonMain/kotlin/Suite.kt --- a/runners/runner-testballoon/src/commonMain/kotlin/Suite.kt +++ b/runners/runner-testballoon/src/commonMain/kotlin/Suite.kt @@ -28,18 +28,51 @@ import opensavvy.prepared.suite.runTestDslSuspend import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext +import kotlin.jvm.JvmName import de.infix.testBalloon.framework.core.TestConfig as BalloonTestConfig +/** + * Declares Prepared-style tests in an existing TestBalloon-style suite. + * + * To declare an entire suite with Prepared, see [preparedSuite]. + */ @Suppress("DSL_MARKER_APPLIED_TO_WRONG_TARGET") @PreparedDslMarker @TestRegistering fun TestSuite.withPrepared( config: TestConfig = TestConfig.Empty, - block: SuiteDsl.() -> Unit, + block: TestBalloonSuiteDsl.() -> Unit, ) { - TestBalloonSuite(this, config).apply(block) + TestBalloonSuiteDsl(this, config).apply(block) } +/** + * Declares a top-level [suite](https://prepared.opensavvy.dev/tutorials/syntax.html) (a group of related tests). + * + * ### Example + * + * ```kotlin + * val myTestSuite by preparedSuite { + * test("A simple test") { + * // … + * } + * + * suite("A nested suite of tests") { + * test("A second test") { + * // … + * } + * + * test("A third test") { + * // … + * } + * } + * } + * ``` + * + * ### IDE support + * + * Tests declared with this DSL can be executed individually with the [TestBalloon IntelliJ plugin](https://plugins.jetbrains.com/plugin/27749-testballoon). + */ @Suppress("DSL_MARKER_APPLIED_TO_WRONG_TARGET") @PreparedDslMarker @TestRegistering @@ -49,18 +82,58 @@ preparedConfig: TestConfig = TestConfig.Empty, compartment: () -> TestCompartment = { TestCompartment.Default }, @TestSuitePropertyName qualifiedPropertyName: String = "", - content: SuiteDsl.() -> Unit, + content: TestBalloonSuiteDsl.() -> Unit, ) = testSuite(name, compartment, balloonConfig, qualifiedPropertyName) { withPrepared(preparedConfig) { content() } } -private class TestBalloonSuite( +/** + * An implementation of Prepared's [SuiteDsl] that is recognized by the [TestBalloon IntelliJ plugin](https://plugins.jetbrains.com/plugin/27749-testballoon). + * + * To create an instance of this class, use [preparedSuite] or [withPrepared]. + */ +class TestBalloonSuiteDsl internal constructor( private val upstream: TestSuiteScope, private val config: TestConfig, ) : SuiteDsl { - override fun suite(name: String, config: TestConfig, block: SuiteDsl.() -> Unit) { + + /** + * Creates a child suite named [name] of the current suite. + * + * ### Simple example + * + * ```kotlin + * suite("An example") { + * test("A test") { … } + * + * suite("A nested suite") { + * test("A nested test 1") { … } + * test("A nested test 2") { … } + * } + * } + * ``` + * + * ### Test configuration + * + * The default configuration for all tests can be passed with the [config] parameter: + * + * ```kotlin + * suite("An example", CoroutineTimeout(2.minutes) + Tag("slow")) { + * … + * } + * ``` + * + * To learn more about the available configuration options, see the subtypes of [TestConfig.Element]. + */ + @TestRegistering + @JvmName("suiteTestBalloon") + fun suite( + name: String, + config: TestConfig = TestConfig.Empty, + block: TestBalloonSuiteDsl.() -> Unit, + ) { val effectiveConfig = this.config + config with(upstream) { @@ -70,6 +143,14 @@ } } + // Necessary to override the interface but also force users to call the more specific overload + // Only the more specific overload has IDE support + @Deprecated("This method is not really deprecated, this is a trick to enhance the IDE experience", level = DeprecationLevel.HIDDEN) + override fun suite(name: String, config: TestConfig, block: SuiteDsl.() -> Unit) { + suite(name, config, block) + } + + @TestRegistering override fun test(name: String, config: TestConfig, block: suspend TestDsl.() -> Unit) { val effectiveConfig = this.config + config -- tangled.sh