Kotlin est un projet brillant. Initialement conçu comme un simple langage JVM, il a ensuite reçu un support de compilation pour toutes les plates-formes grand public, y compris JavaScript.
Introduction. J'ai un projet animalier - un site et une plate-forme API pour la communauté pour le jeu Elite: Dangerous. Le backend est Kotlin / JVM (Ktor + Hibernate), le frontend est Kotlin / JS (KVision + Fomantic UI). Je vous parlerai du projet pour animaux de compagnie un peu plus tard, et plus sur le front.
KVision est un framework frontal pour Kotlin qui combine des idées de différents frameworks de bureau (de Swing et JavaFX à WinForms et Flutter) et des capacités de syntaxe Kotlin, telles que les générateurs DSL.
Fomantic-UI est un fork de Semantic-UI, un framework web HTML / JS qui peut être comparé à Bootstrap, seul Fomantic est plus intéressant.
Il n'y a pas si longtemps, j'ai eu l'idée de relier ces deux mondes et d'écrire une bibliothèque pour KVision, ce qui faciliterait au moins l'écriture de pages KVision avec des éléments Fomantic. Et, comme il sied à un projet open source, j'ai prévu de couvrir la bibliothèque de tests. Cet article portera sur cette aventure.
Le code
Tout d'abord, définissons la tâche. Nous avons le code suivant pour un simple bouton Fomantic entre nos mains:
package com.github.kam1sh.kvision.fomantic
import pl.treksoft.kvision.html.*
import pl.treksoft.kvision.panel.SimplePanel
open class FoButton(text: String) : Button(text = text, classes = setOf("ui", "button")) {
var primary: Boolean = false
set(value) {
if (value) addCssClass("primary") else removeCssClass("primary")
field = value
}
}
fun SimplePanel.foButton(
text: String,
init: (FoButton.() -> Unit)? = null
): FoButton {
val btn = FoButton(text)
init?.invoke(btn)
add(btn)
return btn
}
Et il y a quelques tests:
package com.github.kam1sh.kvision.fomantic
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlinx.browser.document
import kotlinx.coroutines.*
import pl.treksoft.kvision.panel.ContainerType
import pl.treksoft.kvision.panel.Root
class FoButtonTest {
lateinit var kvapp: Root
@BeforeTest
fun before() {
kvapp = Root("kvapp", containerType = ContainerType.NONE, addRow = false)
}
@Test
fun genericButtonTest() {
kvapp.foButton("Button")
assertEqualsHtml("""...""")
}
@Test
fun buttonPrimaryTest() {
val btn = kvapp.foButton("Button") { primary = true }
assertEqualsHtml("""...""")
btn.primary = false
assertEqualsHtml("""...""")
}
}
fun assertEqualsHtml(expected: String, message: String? = null) {
val actual = document.getElementById("kvapp")?.innerHTML
assertEquals(expected, actual, message)
}
: "" KVision div id=kvapp, HTML-.
. div? HTML- - document.body?.insertAdjacentHTML(...)
, , - ?
<source lang="html">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.8.7/dist/semantic.min.css">
<script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.8.7/dist/semantic.min.js"></script>
</head>
<body>
<main>
<div id="kvapp">
</div>
</main>
</body>
</html>
</source>
You've lost karma
Kotlin/JS.
For browser projects, it downloads and installs the Karma test runner with other required dependencies; for Node.js projects, the Mocha test framework is used.
. Karma Mocha. , Karma js- karma.config.d
.
Karma , -:
// karma.config.d/page.js
config.set({
customContextFile: "../../../../../src/test/resources/test.html"
})
test.html, , src/test/resources/test.html
. - , Karma build/js/packages/kvision-fomantic-test/node_modules
, .
, ? ./gradlew browserTest
, ... Disconnected (0 times), because no message in 30000 ms.
, HTML- , JS-. build/js/node_modules/karma/static/context.html
.
main-:
<!-- The scripts need to be in the body DOM element, as some test running frameworks need the body
to have already been created so they can insert their magic into it. For example, if loaded
before body, Angular Scenario test framework fails to find the body and crashes and burns in
an epic manner. -->
<script src="context.js"></script>
<script type="text/javascript">
// Configure our Karma and set up bindings
%CLIENT_CONFIG%
window.__karma__.setupContext(window);
// All served files with the latest timestamps
%MAPPINGS%
</script>
<!-- Dynamically replaced with <script> tags -->
%SCRIPTS%
<!-- Since %SCRIPTS% might include modules, the `loaded()` call needs to be in a module too.
This ensures all the tests will have been declared before karma tries to run them. -->
<script type="module">
window.__karma__.loaded();
</script>
<script nomodule>
window.__karma__.loaded();
</script>
, ... , .
- . ? , HTTP- Ktor . Python async
, pytest pytest-async, .
suspend .
> Task :compileTestKotlinJs FAILED
e: ...src/test/kotlin/com/github/kam1sh/kvision/fomantic/FoButtonTest.kt: (44, 5): Unsupported [suspend test functions]
- Gradle
, runBlocking {}
. ...
runBlocking Kotlin/JVM.
, , , , , by design. GlobalScope.promise
, runBlocking :
fun runBlocking(block: suspend (scope: CoroutineScope) -> Unit) = GlobalScope.promise { block(this) }
. , . Karma :
config.set({
client: {
mocha: {
timeout: 9000
}
}
})
. workaround. UPD: @ilgonmic, , 0. !
Mocha, , , , :
, done-, .
, Promise.
, , . , kotlin-test-js .
, , . , Promise, Mocha .
, , ? -- ?
- Kotest. .
. , .
// build.gradle.kts
testImplementation("io.kotest:kotest-assertions-core-js:4.3.2")
testImplementation("io.kotest:kotest-framework-api-js:4.3.2")
testImplementation("io.kotest:kotest-framework-engine:4.3.2")
class FoButtonTest : FunSpec({
var kvapp: Root? = null
beforeEach {
kvapp = Root("kvapp", containerType = ContainerType.NONE, addRow = false)
}
test("generic button") {
kvapp!!.foButton("Button")
assertEqualsHtml("""...""")
}
test("primary button") {
val btn = kvapp!!.foButton("Button") { primary = true }
assertEqualsHtml("""...""")
btn.primary = false
delay(200)
assertEqualsHtml("""...""")
}
})
kotest , , FunSpec -- .
, , delay() suspend.
:
C'est tout ce que je peux vous dire sur kotest pour le moment. Je continuerai à développer la bibliothèque, et quand elle sera prête, j'annoncerai sa sortie dans la discorde Fomantic et le slack Kotlin / kvision. Et en parallèle j'apprendrai kotest.
Si cela ne vous suffisait pas, alors je m'excuse: je voulais montrer la conclusion ici ./gradlew --debug browserTest
, mais la préparation de ce matériel a déjà été assez retardée en raison de l'apparence de la vie personnelle, donc si vous êtes intéressé, contemplez vous-même les journaux de débogage de Gradle.
Et alors? Eh bien, rien. Mangez Kotlin / JS, buvez du kotest et prenez soin de vous.