For KMP unit tests that run in browser/headlessChr...
# javascript
a
For KMP unit tests that run in browser/headlessChrome I need to load a file from commonTest/resources with my test input data. I've seen variations of this question asked that have hints at a solution but I still can't figure it out, some look like they apply more to a JS only project with more javascript things like webpack added, or node which can load files on the filesystem unlike the browser. How can I do this?
d
I reported this as a bug weeks ago: https://youtrack.jetbrains.com/issue/KT-42923 I've managed to work around it with a karma middleware detailed in a comment on that issue. If you're testing a KMP lib, you're still going to have to create an expected function for loading files. On the jvm you can just use File or whatever, in JS you'd have to use fetch or XMLHttpRequest.
Oh, and because fetch can only retrieve files async, you probably want to make the file loading function suspend and then use the await extension method on the promise returned from fetch. This then leads to this problem: https://youtrack.jetbrains.com/issue/KT-22228 for which there is also a workaround.
You also talk about "JS only project with more javascript things like webpack added". As far as I'm aware, the moment you use KJS (possibly as a part of a KMP project), you're using webpack. Might be good to keep in mind.
a
thanks I will give that a try, didn't think it would be as simple as fetch on a local file with no paths, etc
I am still having some issues with this... first is the syntax on that 2nd page doesn't seem to work "dynamic = promise" is not recognized. Here is a minimal example if i can get this to work...
Copy code
@Test
fun test(): dynamic = promise {
    window.fetch("test.json").then {
        it.json()
    }.then {
        println(it)
    }
}
if I change to Promise<String> then it gives a 404 error. I copied the test.json to multiple folders as well but its also in the jsTest/resource folder
d
yeah, that's why you need the first workaround, detailed in the comment on this issue: https://youtrack.jetbrains.com/issue/KT-42923
loading resources from karma is a huge pita atm
a
I finally got something working, at least on the JS side. Need to figure out how to make it work on commonTest now with Java
d
in my project I simply have an
expect suspend
readFile function that uses fetch in js and getResourceAsStream on jvm
a
You need both right? The expect readFile and runTest to bypass the limitation for suspend functions in test methods?
I got most everything working but unsure how to do this with the pattern above. Currently I have a lot of tests that rely on loading a single large file with the test data. In JVM I did this by extending a TestBase class w/lazy val property to read/parse the data once for all tests.
lazy property is a bit weird with this so I moved it to the constructor. I am not sure how to initialize a base class with data that relies on a suspend function which is a javascript promise, tests fails because data is not loaded yet.
d
test classes get instantiated for every single test, so it doesn't matter whether you load the file in the constructor or in the test method
you could always launch a coroutine in a companion object and store the return Deferred, then just .await() the Deferred at the start of each test function
a
Here is how I ended up doing it using the runTest exactly as from above
expect fun getMyDataAsync(): Deferred<MyData>
protected fun runDataTest(block: suspend (data: MyData) -> Unit) = runTest { if (!isInitialized()) { data = getMyDataAsync().await() } block(data) } companion object { fun isInitialized() = ::data.isInitialized private lateinit var data: MyData }
j
@Daan I've checked your solution from https://github.com/DaanVandenBosch/kotlin-js-karma-resources-test and it solves my problems with reading resources in MPP project. Thanks! Would you mind adding any specific licence to this repo so I could use that workaround with clear conscience? 🙂
d
done
for my hobby project I wrote a gradle plugin which makes it even easier: https://github.com/DaanVandenBosch/phantasmal-world/tree/kotlin/buildSrc (also MIT licensed)
j
Thank you!