I’m using `runTest` to perform a test of some GraphQL client logic (mocking the underlying Apollo co...
s

Sam Pengilly

over 2 years ago
I’m using
runTest
to perform a test of some GraphQL client logic (mocking the underlying Apollo code and testing my own behaviours on top). This test has been fine for months, but for some reason it’s now acting flaky in the CI environment (and seemingly only in the CI environment), triggering the ā€œUncompletedCoroutinesError: After waiting for 10s, the test coroutine is not completingā€ error. I can’t see anything in the body of the test that would be causing a hung coroutine. Could I get a sanity check on it from someone?
@Test
fun `should return parsed data upon network success`() = runTest {
    // Mocks the `call.execute()` suspending function to return an immediate result

    val call = successApolloCall(data = TestQueryData, errors = null)
    val mockApolloClient = mockk<ApolloClient> { every { query(TestQuery) } returns call }

    // executeQuery just wraps the Apollo query/execute calls to add retry behaviours and catching any exceptions using Arrow's Either
    // The retry policy uses Arrow's Scheduler which just uses delay() under the hood and should get skipped in test execution?

    val result = MyWrappingClient(mockApolloClient).executeQuery(TestQuery) { data, errors ->
        // Part of my client API that takes GraphQL response/error data and parses it
        (data == TestQueryData && errors == null).right()
    }

    result shouldBeRight true
    coVerify(exactly = 1) { call.execute() }
}
I’m really struggling with the CORS plugin and preflight requests, OPTION calls give me `403`. A sim...
j

Jonas Helgemo

about 3 years ago
I’m really struggling with the CORS plugin and preflight requests, OPTION calls give me
403
. A simple way to recreate the problem is running the example from the docs: https://github.com/ktorio/ktor-documentation/tree/main/codeSnippets/snippets/cors-backend:
package com.example

import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.plugins.cors.routing.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.serialization.*
import kotlinx.serialization.json.*

@Serializable
data class Customer(val id: Int, val firstName: String, val lastName: String)

fun Application.main() {
    install(CORS) {
        allowHost("0.0.0.0:8081")
        allowHeader(HttpHeaders.ContentType)
    }

    val customerStorage = mutableListOf<Customer>()
    install(ContentNegotiation) {
        json(Json)
    }
    routing {
        post("/customer") {
            val customer = call.receive<Customer>()
            customerStorage.add(customer)
            call.respondText("Customer stored correctly", status = HttpStatusCode.Created)
        }
    }
}
and then run the following:
curl -H "Origin: <http://0.0.0.0:8081>" -H "Access-Control-Request-Method: POST" -H "Access-Control-Request-Headers: Origin, X-Requested-With" -X OPTIONS --verbose <http://localhost:8080/customer>
I don’t understand why this doesn’t give me a
2XX
response with correct preflight headers. I have looked everywhere for a solution, but to no avail. A similar thread and issue was discussed here: https://kotlinlang.slack.com/archives/C0A974TJ9/p1655722302810509, but this seems to be a slightly different case as the CORS-plugin is installed inside the routing-block where this is a known issue. My current workaround is to add a catch-all OPTIONS-block, but this feels like a dirty hack as the response headers will not be correct in different cases. Any tips on how to fix this? Using 2.1.2 of Ktor and CORS-plugin