Refactoring, more nested test generation, split QUnit 1 and 2 (is that a good idea at all)
diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/test/JSTestGenerator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/test/JSTestGenerator.kt
index 882a31a..f269dbb 100644
--- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/test/JSTestGenerator.kt
+++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/test/JSTestGenerator.kt
@@ -17,13 +17,11 @@
package org.jetbrains.kotlin.js.translate.test
import org.jetbrains.kotlin.descriptors.*
-import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
@@ -42,25 +40,39 @@
return JsNameRef(name, JsNameRef("Kotlin"))
}
- fun generateTestCalls(moduleDescriptor: ModuleDescriptor) = generateTestCalls(moduleDescriptor, FqName.ROOT)
+ fun generateTestCalls(moduleDescriptor: ModuleDescriptor) {
+ val rootFunction = JsFunction(context.scope(), JsBlock(), "root suite function")
- private fun generateTestCalls(moduleDescriptor: ModuleDescriptor, packageName: FqName) {
+ generateTestCalls(moduleDescriptor, FqName.ROOT, rootFunction)
+
+ if (!rootFunction.body.isEmpty) {
+ context.addTopLevelStatement(JsInvocation(suiteRef, JsStringLiteral(""), rootFunction).makeStmt())
+ }
+ }
+
+ private fun generateTestCalls(moduleDescriptor: ModuleDescriptor, packageName: FqName, parentFun: JsFunction) {
for (packageDescriptor in moduleDescriptor.getPackage(packageName).fragments) {
if (DescriptorUtils.getContainingModule(packageDescriptor) !== moduleDescriptor) continue
packageDescriptor.getMemberScope().getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS, MemberScope.ALL_NAME_FILTER).forEach {
if (it is ClassDescriptor) {
- generateTestFunctions(it)
+ generateTestFunctions(it, parentFun)
}
}
}
for (subpackageName in moduleDescriptor.getSubPackagesOf(packageName, MemberScope.ALL_NAME_FILTER)) {
- generateTestCalls(moduleDescriptor, subpackageName)
+ val subPackageFunction = JsFunction(context.scope(), JsBlock(), "${subpackageName.asString()} package suite function")
+
+ generateTestCalls(moduleDescriptor, subpackageName, subPackageFunction)
+
+ if (!subPackageFunction.body.isEmpty) {
+ parentFun.body.statements += JsInvocation(suiteRef, JsStringLiteral(subpackageName.shortName().asString()), subPackageFunction).makeStmt()
+ }
}
}
- private fun generateTestFunctions(classDescriptor: ClassDescriptor) {
+ private fun generateTestFunctions(classDescriptor: ClassDescriptor, parentFun: JsFunction) {
if (classDescriptor.modality === Modality.ABSTRACT) return
val suiteFunction = JsFunction(context.scope(), JsBlock(), "suite function")
@@ -74,7 +86,7 @@
if (!suiteFunction.body.isEmpty) {
val suiteName = JsStringLiteral(classDescriptor.name.toString())
- context.addTopLevelStatement(JsInvocation(classDescriptor.ref, suiteName, suiteFunction).makeStmt())
+ parentFun.body.statements += JsInvocation(classDescriptor.ref, suiteName, suiteFunction).makeStmt()
}
}
@@ -124,13 +136,13 @@
* }
*/
private val FunctionDescriptor.isTest
- get() = annotationFinder("Test", "kotlin.test", "org.junit")
+ get() = annotationFinder("Test", "kotlin.test", "org.junit") // Support both ways for now.
private val DeclarationDescriptor.isIgnored
- get() = annotationFinder("Ignore", "kotlin.test")
+ get() = annotationFinder("Ignore", "kotlin.test")
private val DeclarationDescriptor.isFocused
- get() = annotationFinder("Only", "kotlin.test")
+ get() = annotationFinder("Only", "kotlin.test")
private fun DeclarationDescriptor.annotationFinder(shortName: String, vararg packages: String) = packages.any { packageName ->
annotations.hasAnnotation(FqName("$packageName.$shortName"))
diff --git a/libraries/kotlin.test/js/it/package.json b/libraries/kotlin.test/js/it/package.json
index 59e2ed6..390f9de 100644
--- a/libraries/kotlin.test/js/it/package.json
+++ b/libraries/kotlin.test/js/it/package.json
@@ -17,7 +17,7 @@
"jasmine": "^2.6.0",
"jest": "^20.0.4",
"mocha": "^3.4.2",
- "qunit": "^1.0.0",
+ "qunitjs": "^2.3.3",
"tape": "^4.6.3",
"watchify": "^3.9.0"
},
diff --git a/libraries/kotlin.test/js/src/main/kotlin/TestApi.kt b/libraries/kotlin.test/js/src/main/kotlin/TestApi.kt
index 3ac71c0..4f8e608 100644
--- a/libraries/kotlin.test/js/src/main/kotlin/TestApi.kt
+++ b/libraries/kotlin.test/js/src/main/kotlin/TestApi.kt
@@ -67,14 +67,14 @@
internal var currentAdapter: FrameworkAdapter = detectAdapter()
internal fun detectAdapter() = when {
- isQUnit() -> QUnitAdapter()
+ isQUnit2() -> QUnit2Adapter()
isJasmine() -> JasmineAdapter()
isMocha() -> MochaAdapter()
else -> BareAdapter()
}
private val NAME_TO_ADAPTER: Map<String, () -> FrameworkAdapter> = mapOf(
- "qunit" to ::QUnitAdapter,
+ "qunit" to { if (isQUnit1()) QUnit2Adapter() else QUnit2Adapter() },
"jasmine" to ::JasmineAdapter,
"mocha" to ::MochaAdapter,
"auto" to ::detectAdapter)
diff --git a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/BareAdapter.kt b/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/BareAdapter.kt
index eb96f75..8e8ec5a 100644
--- a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/BareAdapter.kt
+++ b/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/BareAdapter.kt
@@ -16,6 +16,8 @@
package kotlin.test.adapters
+import kotlin.test.FrameworkAdapter
+
/**
* A fallback adapter for the case when no framework is detected.
*/
diff --git a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/Externals.kt b/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/Externals.kt
index b33752a..5372974 100644
--- a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/Externals.kt
+++ b/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/Externals.kt
@@ -40,10 +40,12 @@
external fun fdescribe(name: String, fn: () -> Unit)
-internal fun isQUnit() = jsTypeOf(QUnit) !== "undefined"
-
private fun isFunction(a: String) = js("typeof a === 'function'")
+internal fun isQUnit1() = jsTypeOf(QUnit) !== "undefined" && isFunction("ok")
+
+internal fun isQUnit2() = jsTypeOf(QUnit) !== "undefined" && isFunction("QUnit.module.skip") && isFunction("QUnit.module.only")
+
internal fun isJasmine() = isFunction("describe") && isFunction("it") && isFunction("fit")
internal fun isMocha() = isFunction("describe") && isFunction("it") && isFunction("it.only")
diff --git a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/FrameworkAdapter.kt b/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/FrameworkAdapter.kt
deleted file mode 100644
index 0c46294..0000000
--- a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/FrameworkAdapter.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2010-2017 JetBrains s.r.o.
- *
- * 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 kotlin.test.adapters
-
-external interface FrameworkAdapter {
- fun suite(name: String, suiteFn: () -> Unit)
-
- fun xsuite(name: String, suiteFn: () -> Unit)
-
- fun fsuite(name: String, suiteFn: () -> Unit)
-
- fun test(name: String, testFn: () -> Unit)
-
- fun xtest(name: String, testFn: () -> Unit)
-
- fun ftest(name: String, testFn: () -> Unit)
-}
diff --git a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/JasmineAdapter.kt b/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/JasmineAdapter.kt
index 0af1dc0..2f1d87a 100644
--- a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/JasmineAdapter.kt
+++ b/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/JasmineAdapter.kt
@@ -16,6 +16,8 @@
package kotlin.test.adapters
+import kotlin.test.FrameworkAdapter
+
/**
* Jasmine adapter
*/
diff --git a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/MochaAdapter.kt b/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/MochaAdapter.kt
index 51a392d..19d532e 100644
--- a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/MochaAdapter.kt
+++ b/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/MochaAdapter.kt
@@ -16,6 +16,8 @@
package kotlin.test.adapters
+import kotlin.test.FrameworkAdapter
+
/**
* Mocha adapter
*/
diff --git a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/QUnitAdapter.kt b/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/QUnit1Adapter.kt
similarity index 71%
rename from libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/QUnitAdapter.kt
rename to libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/QUnit1Adapter.kt
index 3eeeaa2..97eb489 100644
--- a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/QUnitAdapter.kt
+++ b/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/adapters/QUnit1Adapter.kt
@@ -16,12 +16,13 @@
package kotlin.test.adapters
+import kotlin.test.FrameworkAdapter
import kotlin.test.assertHook
/**
* QUnit adapter
*/
-internal class QUnitAdapter: BareAdapter() {
+internal class QUnit1Adapter: BareAdapter() {
override fun runTest(testFn: () -> Unit,
names: Sequence<String>,
@@ -38,18 +39,8 @@
}
private fun wrapTest(testFn: () -> Unit): (dynamic) -> Unit = { assert ->
- if (js("typeof assert !== 'function'")) {
- assertHook = { result -> assert.ok(result.result, result.lazyMessage()) }
- }
- else {
- assertHook = { result ->
- val data = js("{}")
- data.result = result.result
- data.actual = result.actual
- data.expected = result.expected
- data.message = result.lazyMessage()
- assert.pushResult(data)
- }
+ assertHook = { testResult ->
+ assert.ok(testResult.result, testResult.lazyMessage())
}
testFn()
}