From 3a3c959f353e8987212f89720f4cac31df4e50f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Fri, 31 Jul 2026 12:05:26 +0200 Subject: [PATCH] feat(runner-testballoon): Support the TestBalloon IntelliJ plugin in preparedSuite --- .../src/commonMain/kotlin/Suite.kt | 59 +++++++++++++++++-- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/runners/runner-testballoon/src/commonMain/kotlin/Suite.kt b/runners/runner-testballoon/src/commonMain/kotlin/Suite.kt index 81b0ae5..a758f96 100644 --- a/runners/runner-testballoon/src/commonMain/kotlin/Suite.kt +++ b/runners/runner-testballoon/src/commonMain/kotlin/Suite.kt @@ -28,6 +28,7 @@ import opensavvy.prepared.suite.config.TestConfig 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 @Suppress("DSL_MARKER_APPLIED_TO_WRONG_TARGET") @@ -35,9 +36,9 @@ import de.infix.testBalloon.framework.core.TestConfig as BalloonTestConfig @TestRegistering fun TestSuite.withPrepared( config: TestConfig = TestConfig.Empty, - block: SuiteDsl.() -> Unit, + block: TestBalloonSuiteDsl.() -> Unit, ) { - TestBalloonSuite(this, config).apply(block) + TestBalloonSuiteDsl(this, config).apply(block) } @Suppress("DSL_MARKER_APPLIED_TO_WRONG_TARGET") @@ -49,18 +50,58 @@ fun preparedSuite( 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 +111,14 @@ private class TestBalloonSuite( } } + // 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 -- 2.51.2