I have some code which downloads a file from the w...
# webassembly
m
I have some code which downloads a file from the web via Ktor client 3.0.0-rc-2. The corresponding unit test works on all platforms except wasmJs. On wasmJs the test seems to get stuck in the network call and outputs
Copy code
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
1. Does anybody know where this output line is coming from and what it is trying to tell me? 2. What is the correct HttpClientEngineFactory for wasmJs? I am currently trying
io.ktor.client.engine.js.Js
. 3. Is there anything special to configure for wasmJs?
As far as I could find out this message comes from node.js/mocha.js although this also doesn’t make me wiser about what to do with it in Kotlin.
o
What test framework are you using?
m
Just
implementation(kotlin("test"))
o
In Kotest, I put in extra code to disable the default 2-second timeout: https://github.com/kotest/kotest/blob/2f9215c2f0519e08fe94ee6b37431fde736c1424/kot[…]mJsMain/kotlin/io/kotest/engine/KotlinJsTestFramework.wasmJs.kt This may be missing in kotlin-test.
j
Definitely not. Why should an assertion library be concerned about a runner's timeout?
There's typesafe KGP build DSL to configure the timeout of the selected JS runner
o
Why should an assertion library be concerned about a runner's timeout?
It's not the assertion library but the framework, which actually runs multiplatform tests. The framework has its own cross-platform timeout configurations. The JS "runner" is just an implementation detail on one platform and should not interfere with the framework user's decision on test timeouts, which might have been set in common code.
j
kotlin-test is not a framework, though
o
Depends on what you call a framework. If it calls my code, I tend to call stuff a framework. So for me, kotlin-test qualifies. And before that, I was referring to the Kotest framework as opposed to the Kotest assertion library.
j
I was replying to your claim that kotlin-test was potentially missing this timeout removal.
o
I just wasn't sure, that's why I said "may be missing". But fortunately, you pointed to the configuration option that could solve the original problem. All good, right?
m
I have added
Copy code
js {
    nodejs {
      testTask {
        useMocha {
          timeout = "5s"
        }
      }
    }
  }
to my build script as shown in the linked example but that only results in an endless list of configuration error messages which brings me back to my original questions points 2 and 3. Is this actually supposed to work for wasmJs?
j
Yes it works for wasmJs, too
Did you add it to the wasmJs target?
m
That’s how I put it into my build.gradle.kts now:
Copy code
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
wasmJs {
    browser()
    binaries.library()
    nodejs {
        testTask {
            useMocha {
                timeout = "5s"
            }
        }
    }
}
This works in so far now as the test gets compiled and runs but its output is still:
Copy code
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
j
This is not specific to wasm. Kotlin-js is also impacted by this. We've been adding workarounds for the very short default timeout in ktor for years. Mocha and karma are just very slow. And when you have a lot of async stuff happening in tests, things can pile up. Especially when you are running integration tests. 2 seconds just isn't a great default.
m
But the problem is not Ktor here as far as I understand the issue. My Ktor client is configured like this:
Copy code
val httpClient = HttpClient(engineFactory) {
    install(HttpTimeout) {
        requestTimeoutMillis = 30_000
        connectTimeoutMillis = 5_000
    }
    install(HttpRequestRetry) {
        retryOnServerErrors(maxRetries = 5)
        constantDelay()
    }
    install(ContentEncoding) {
        deflate(1.0F)
        gzip(0.9F)
    }
    followRedirects = true // This is the default anyway.
}
The above shown timeout setting for Mocha just doesn’t seem to have any effect. I actually ran this code from the wasmJs application and did not get such a timeout. But that did not help me much either because what I wanted to do just resulted in a CORS error. In the end it turns out that what I wanted to do is just not possible with a web-app, so I’ll have to stick to writing desktop apps 😢.