diff --git a/libraries/kotlin.test/wasm/js/src/main/kotlin/kotlin/test/JasmineLikeAdapter.kt b/libraries/kotlin.test/wasm/js/src/main/kotlin/kotlin/test/JasmineLikeAdapter.kt index e9a23c9d8a0..1af68e5e0bd 100644 --- a/libraries/kotlin.test/wasm/js/src/main/kotlin/kotlin/test/JasmineLikeAdapter.kt +++ b/libraries/kotlin.test/wasm/js/src/main/kotlin/kotlin/test/JasmineLikeAdapter.kt @@ -5,7 +5,6 @@ package kotlin.test -import kotlin.test.FrameworkAdapter import kotlin.js.Promise // Need to wrap into additional lambdas so that js launcher will work without Mocha or any other testing framework @@ -67,4 +66,27 @@ internal class JasmineLikeAdapter : FrameworkAdapter { } } } -} \ No newline at end of file +} + +internal external interface ExternalFrameworkAdapter : JsAny { + fun suite(name: String, ignored: Boolean, suiteFn: () -> Unit) + fun test(name: String, ignored: Boolean, testFn: () -> JsReference?) +} + +private fun createExternalJasmineLikeAdapter( + suiteFn: (String, Boolean, () -> Unit) -> Unit, + testFn: (String, Boolean, () -> JsReference?) -> Unit +): ExternalFrameworkAdapter = js("{ return { suite: suiteFn, test: testFn } }") + +private class ExternalAdapterWrapper(private val externalAdapter: ExternalFrameworkAdapter) : FrameworkAdapter { + override fun suite(name: String, ignored: Boolean, suiteFn: () -> Unit) = externalAdapter.suite(name, ignored, suiteFn) + override fun test(name: String, ignored: Boolean, testFn: () -> Any?) = externalAdapter.test(name, ignored, { testFn()?.toJsReference() }) +} + +internal fun JasmineLikeAdapter.externalize(): ExternalFrameworkAdapter = + createExternalJasmineLikeAdapter( + suiteFn = this::suite, + testFn = { name, ignored, testFn -> this.test(name, ignored, { testFn()?.get() }) } + ) + +internal fun ExternalFrameworkAdapter.internalize(): FrameworkAdapter = ExternalAdapterWrapper(this) diff --git a/libraries/kotlin.test/wasm/js/src/main/kotlin/kotlin/test/TestApi.kt b/libraries/kotlin.test/wasm/js/src/main/kotlin/kotlin/test/TestApi.kt index 9dc2e278d57..ed000934ab2 100644 --- a/libraries/kotlin.test/wasm/js/src/main/kotlin/kotlin/test/TestApi.kt +++ b/libraries/kotlin.test/wasm/js/src/main/kotlin/kotlin/test/TestApi.kt @@ -5,6 +5,9 @@ package kotlin.test +private fun isJasmine(): Boolean = + js("typeof describe === 'function' && typeof it === 'function'") + /** * Overrides current framework adapter with a provided instance of [FrameworkAdapter]. Use in order to support custom test frameworks. * @@ -17,11 +20,28 @@ internal fun setAdapter(adapter: FrameworkAdapter) { internal var currentAdapter: FrameworkAdapter? = null -private fun isJasmine(): Boolean = - js("typeof describe === 'function' && typeof it === 'function'") +@JsName("kotlinTest") +internal external val kotlinTestNamespace: ExternalKotlinTestNamespace? + +internal external interface ExternalKotlinTestNamespace : JsAny { + public val adapterTransformer: ((ExternalFrameworkAdapter) -> ExternalFrameworkAdapter)? +} internal actual fun adapter(): FrameworkAdapter { - val result = currentAdapter ?: if (isJasmine()) JasmineLikeAdapter() else TeamcityAdapterWithPromiseSupport() - currentAdapter = result - return result + currentAdapter?.let { return it } + + val adapter: FrameworkAdapter + if (isJasmine()) { + val jasmineLikeAdapter = JasmineLikeAdapter() + val transformer = kotlinTestNamespace?.adapterTransformer + if (transformer != null) { + adapter = transformer(jasmineLikeAdapter.externalize()).internalize() + } else { + adapter = jasmineLikeAdapter + } + } else { + adapter = TeamcityAdapterWithPromiseSupport() + } + currentAdapter = adapter + return adapter } \ No newline at end of file