Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ end_of_line = crlf

[*.{md,mdx}]
trim_trailing_whitespace = false

[*.{kt,kts}]
ij_kotlin_name_count_to_use_star_import = 999
ij_kotlin_name_count_to_use_star_import_for_members = 999
3 changes: 2 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
ktor-server-auth = { module = "io.ktor:ktor-server-auth", version.ref = "ktor" }
ktor-server-test-host = { module = "io.ktor:ktor-server-test-host", version.ref = "ktor" }
kotest = { module = "io.kotest:kotest-assertions-core", version.ref = "kotest" }
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit-jupiter" }
junit-launcher = { module = "org.junit.platform:junit-platform-launcher", version.ref = "junit-jupiter" }
junit-jupiter-core = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit-jupiter" }
kotlinx-benchmark-runtime = { module = "org.jetbrains.kotlinx:kotlinx-benchmark-runtime", version.ref = "kotlinx-benchmark" }
3 changes: 2 additions & 1 deletion kgraphql-ktor-stitched/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ dependencies {
implementation(libs.ktor.client.cio)
implementation(libs.kotlinx.serialization.json)

testImplementation(libs.junit.jupiter.api)
testImplementation(libs.junit.jupiter.core)
testImplementation(libs.kotest)
testImplementation(libs.ktor.server.test.host)
testImplementation(testFixtures(project(":kgraphql")))
testRuntimeOnly(libs.junit.launcher)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.apurebase.kgraphql.KGraphQL
import com.apurebase.kgraphql.request.Introspection
import com.apurebase.kgraphql.schema.SchemaPrinter
import io.kotest.matchers.shouldBe
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test

class IntrospectedSchemaTest {
Expand All @@ -15,7 +16,7 @@ class IntrospectedSchemaTest {
}

@Test
fun `introspected schema should result in the same SDL as the schema itself`() {
fun `introspected schema should result in the same SDL as the schema itself`() = runTest {
val schema = KGraphQL.schema {
extendedScalars()

Expand All @@ -32,7 +33,7 @@ class IntrospectedSchemaTest {
}

val schemaFromIntrospection = IntrospectedSchema.fromIntrospectionResponse(
schema.executeBlocking(Introspection.query())
schema.execute(Introspection.query())
)

SchemaPrinter().print(schemaFromIntrospection) shouldBe SchemaPrinter().print(schema)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import com.apurebase.kgraphql.stitched.schema.configuration.StitchedSchemaConfig
import com.apurebase.kgraphql.stitched.schema.execution.RemoteRequestExecutor
import com.fasterxml.jackson.databind.JsonNode
import io.kotest.matchers.shouldBe
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
import java.util.Locale
import java.util.UUID
Expand All @@ -41,8 +42,8 @@ class StitchedSchemaTest {
* Executes the default introspection query against this [Schema] and returns it
* as parsed [IntrospectedSchema]
*/
private fun Schema.introspected(): IntrospectedSchema {
val introspectionResponse = executeBlocking(Introspection.query())
private suspend fun Schema.introspected(): IntrospectedSchema {
val introspectionResponse = execute(Introspection.query())
return IntrospectedSchema.fromIntrospectionResponse(introspectionResponse)
}

Expand Down Expand Up @@ -77,7 +78,7 @@ class StitchedSchemaTest {
}

@Test
fun `stitched schema should skip duplicate types by name and prefer local types`() {
fun `stitched schema should skip duplicate types by name and prefer local types`() = runTest {
val schema = StitchedKGraphQL.stitchedSchema {
configure {
remoteExecutor = DummyRemoteRequestExecutor
Expand Down Expand Up @@ -113,7 +114,7 @@ class StitchedSchemaTest {
}

@Test
fun `stitched schema should include local and remote types with proper fields`() {
fun `stitched schema should include local and remote types with proper fields`() = runTest {
val schema = StitchedKGraphQL.stitchedSchema {
configure {
remoteExecutor = DummyRemoteRequestExecutor
Expand Down Expand Up @@ -174,7 +175,7 @@ class StitchedSchemaTest {
}

@Test
fun `stitched schema should include union types with proper possible types`() {
fun `stitched schema should include union types with proper possible types`() = runTest {
val schema = StitchedKGraphQL.stitchedSchema {
configure {
remoteExecutor = DummyRemoteRequestExecutor
Expand Down Expand Up @@ -214,7 +215,7 @@ class StitchedSchemaTest {
}

@Test
fun `stitched schema should include all local and remote queries`() {
fun `stitched schema should include all local and remote queries`() = runTest {
val schema = StitchedKGraphQL.stitchedSchema {
configure {
remoteExecutor = DummyRemoteRequestExecutor
Expand Down Expand Up @@ -283,7 +284,7 @@ class StitchedSchemaTest {
}

@Test
fun `stitched schema should include all local and remote mutations`() {
fun `stitched schema should include all local and remote mutations`() = runTest {
val schema = StitchedKGraphQL.stitchedSchema {
configure {
remoteExecutor = DummyRemoteRequestExecutor
Expand Down Expand Up @@ -351,7 +352,7 @@ class StitchedSchemaTest {
}

@Test
fun `schema with remote input types should be printed as expected`() {
fun `schema with remote input types should be printed as expected`() = runTest {
data class TestObject(val name: String)

val schema = StitchedKGraphQL.stitchedSchema {
Expand Down Expand Up @@ -394,7 +395,7 @@ class StitchedSchemaTest {
}

@Test
fun `schema with remote extension properties should be printed as expected`() {
fun `schema with remote extension properties should be printed as expected`() = runTest {
data class TestObject(val name: String)

val schema = StitchedKGraphQL.stitchedSchema {
Expand Down Expand Up @@ -440,7 +441,7 @@ class StitchedSchemaTest {
}

@Test
fun `schema with deprecated remote fields should be printed as expected`() {
fun `schema with deprecated remote fields should be printed as expected`() = runTest {
data class TestObject(val name: String)

val schema = StitchedKGraphQL.stitchedSchema {
Expand Down Expand Up @@ -489,7 +490,7 @@ class StitchedSchemaTest {
class Face(override val value: String, override val value2: Boolean = false) : InterInter

@Test
fun `schema with remote interfaces should be printed as expected`() {
fun `schema with remote interfaces should be printed as expected`() = runTest {
val schema = StitchedKGraphQL.stitchedSchema {
configure {
remoteExecutor = DummyRemoteRequestExecutor
Expand Down Expand Up @@ -655,7 +656,7 @@ class StitchedSchemaTest {

// TODO: make configurable? this doesn't seem like *always* intended
@Test
fun `stitched operations should include optional input arguments`() {
fun `stitched operations should include optional input arguments`() = runTest {
data class SimpleClass(val existing: String)

val schema = StitchedKGraphQL.stitchedSchema {
Expand Down Expand Up @@ -715,7 +716,7 @@ class StitchedSchemaTest {
SchemaPrinter().print(schema) shouldBe expectedSDL
SchemaPrinter().print(schema.introspected()) shouldBe expectedSDL

schema.executeBlocking(
schema.execute(
"""
{
__type(name: "SimpleClass") { name kind fields { name } }
Expand Down
4 changes: 3 additions & 1 deletion kgraphql-ktor/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ dependencies {
implementation(libs.kotlinx.serialization.json)
implementation(libs.ktor.server.core)

testImplementation(libs.junit.jupiter.api)
testImplementation(libs.junit.jupiter.core)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.kotest)
testImplementation(libs.ktor.server.test.host)
testImplementation(libs.ktor.server.auth)
testRuntimeOnly(libs.junit.launcher)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.http.contentType
import io.ktor.server.application.ApplicationCall
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.add
import kotlinx.serialization.json.put
import kotlinx.serialization.json.putJsonArray
Expand All @@ -18,7 +18,7 @@ class KtorFeatureTest : KtorTest() {
data class User(val id: Int = -1, val name: String = "")

@Test
fun `Simple query test`() {
fun `Simple query test`() = runTest {
val server = withServer {
query("hello") {
resolver { -> "World!" }
Expand All @@ -28,14 +28,13 @@ class KtorFeatureTest : KtorTest() {
val response = server("query") {
field("hello")
}
runBlocking {
response.bodyAsText() shouldBe "{\"data\":{\"hello\":\"World!\"}}"
response.contentType() shouldBe ContentType.Application.Json
}

response.bodyAsText() shouldBe "{\"data\":{\"hello\":\"World!\"}}"
response.contentType() shouldBe ContentType.Application.Json
}

@Test
fun `Simple mutation test`() {
fun `Simple mutation test`() = runTest {
val server = withServer {
query("dummy") {
resolver { -> "dummy" }
Expand All @@ -48,17 +47,16 @@ class KtorFeatureTest : KtorTest() {
val response = server("mutation") {
field("hello")
}
runBlocking {
response.bodyAsText() shouldBe "{\"data\":{\"hello\":\"World! mutation\"}}"
response.contentType() shouldBe ContentType.Application.Json
}

response.bodyAsText() shouldBe "{\"data\":{\"hello\":\"World! mutation\"}}"
response.contentType() shouldBe ContentType.Application.Json
}

data class Actor(val name: String, val age: Int)
data class UserData(val username: String, val stuff: String)

@Test
fun `Simple context test`() {
fun `Simple context test`() = runTest {
val georgeName = "George"
val contextSetup: ContextBuilder.(ApplicationCall) -> Unit = { _ ->
+UserData(georgeName, "STUFF")
Expand Down Expand Up @@ -90,20 +88,16 @@ class KtorFeatureTest : KtorTest() {
field("name(addStuff: true)")
}
}
runBlocking {
response.bodyAsText() shouldBe "{\"data\":{\"actor\":{\"name\":\"${georgeName}STUFF\"}}}"
response.contentType() shouldBe ContentType.Application.Json
}
response.bodyAsText() shouldBe "{\"data\":{\"actor\":{\"name\":\"${georgeName}STUFF\"}}}"
response.contentType() shouldBe ContentType.Application.Json

response = server("query") {
field("actor") {
field("nickname")
}
}
runBlocking {
response.bodyAsText() shouldBe "{\"data\":{\"actor\":{\"nickname\":\"Hodor and $georgeName\"}}}"
response.contentType() shouldBe ContentType.Application.Json
}
response.bodyAsText() shouldBe "{\"data\":{\"actor\":{\"nickname\":\"Hodor and $georgeName\"}}}"
response.contentType() shouldBe ContentType.Application.Json
}

enum class MockEnum { M1, M2 }
Expand All @@ -113,7 +107,7 @@ class KtorFeatureTest : KtorTest() {
data class InputTwo(val one: InputOne, val quantity: Int, val tokens: List<String>)

@Test
fun `Simple variables test`() {
fun `Simple variables test`() = runTest {
val server = withServer {
inputType<InputTwo>()
query("test") { resolver { input: InputTwo -> "success: $input" } }
Expand All @@ -136,14 +130,12 @@ class KtorFeatureTest : KtorTest() {
}
}
}
runBlocking {
response.bodyAsText() shouldBe "{\"data\":{\"test\":\"success: InputTwo(one=InputOne(enum=M1, id=M1), quantity=3434, tokens=[23, 34, 21, 434])\"}}"
response.contentType() shouldBe ContentType.Application.Json
}
response.bodyAsText() shouldBe "{\"data\":{\"test\":\"success: InputTwo(one=InputOne(enum=M1, id=M1), quantity=3434, tokens=[23, 34, 21, 434])\"}}"
response.contentType() shouldBe ContentType.Application.Json
}

@Test
fun `Error response test`() {
fun `Error response test`() = runTest {
val server = withServer {
query("actor") {
resolver { -> Actor("George", 23) }
Expand All @@ -155,10 +147,8 @@ class KtorFeatureTest : KtorTest() {
field("nickname")
}
}
runBlocking {
response.bodyAsText() shouldBe "{\"errors\":[{\"message\":\"Property nickname on Actor does not exist\",\"locations\":[{\"line\":3,\"column\":1}],\"path\":[],\"extensions\":{\"type\":\"GRAPHQL_VALIDATION_FAILED\"}}]}"
response.contentType() shouldBe ContentType.Application.Json
}
response.bodyAsText() shouldBe "{\"errors\":[{\"message\":\"Property nickname on Actor does not exist\",\"locations\":[{\"line\":3,\"column\":1}],\"path\":[],\"extensions\":{\"type\":\"GRAPHQL_VALIDATION_FAILED\"}}]}"
response.contentType() shouldBe ContentType.Application.Json
}

@Test
Expand All @@ -174,8 +164,6 @@ class KtorFeatureTest : KtorTest() {
field("nickname")
}
}
runBlocking {
response.status shouldBe HttpStatusCode.Unauthorized
}
response.status shouldBe HttpStatusCode.Unauthorized
}
}
3 changes: 2 additions & 1 deletion kgraphql/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ dependencies {
implementation(libs.aedile)

testImplementation(libs.kotest)
testImplementation(libs.junit.jupiter.api)
testImplementation(libs.junit.jupiter.core)
testImplementation(libs.junit.jupiter.params)
testImplementation(libs.kotlinx.coroutines.debug)
testImplementation(libs.kotlinx.coroutines.test)
testRuntimeOnly(libs.junit.launcher)

testFixturesImplementation(libs.kotest)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ fun assertNoErrors(map: Map<*, *>) {
if (map["data"] == null) throw AssertionError("Data is null")
}

fun executeEqualQueries(schema: Schema, expected: Map<*, *>, vararg queries: String) {
suspend fun executeEqualQueries(schema: Schema, expected: Map<*, *>, vararg queries: String) {
queries.map { request ->
schema.executeBlocking(request).deserialize()
schema.execute(request).deserialize()
}.forAll { map ->
map shouldBe expected
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.apurebase.kgraphql.deserialize
import com.apurebase.kgraphql.expect
import com.apurebase.kgraphql.extract
import io.kotest.matchers.shouldBe
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test

class AccessRulesTest {
Expand Down Expand Up @@ -38,32 +39,32 @@ class AccessRulesTest {
}

@Test
fun `allow when matching`() {
fun `allow when matching`() = runTest {
val kobe = deserialize(
schema.executeBlocking("{black_mamba{name}}", context = context { +"LAKERS" })
schema.execute("{black_mamba{name}}", context = context { +"LAKERS" })
).extract<String>("data/black_mamba/name")

kobe shouldBe "KOBE"
}

@Test
fun `reject when not matching`() {
fun `reject when not matching`() = runTest {
expect<IllegalAccessException>("ILLEGAL ACCESS") {
deserialize(
schema.executeBlocking("{ black_mamba {id} }", context = context { +"LAKERS" })
schema.execute("{ black_mamba {id} }", context = context { +"LAKERS" })
).extract<String>("data/black_mamba/id")
}
}

@Test
fun `allow property resolver access rule`() {
deserialize(schema.executeBlocking("{white_mamba {item}}")).extract<String>("data/white_mamba/item") shouldBe "item"
fun `allow property resolver access rule`() = runTest {
deserialize(schema.execute("{white_mamba {item}}")).extract<String>("data/white_mamba/item") shouldBe "item"
}

@Test
fun `reject property resolver access rule`() {
fun `reject property resolver access rule`() = runTest {
expect<IllegalAccessException>("ILLEGAL ACCESS") {
schema.executeBlocking("{black_mamba {item}}", context = context { +"LAKERS" }).also(::println)
schema.execute("{black_mamba {item}}", context = context { +"LAKERS" }).also(::println)
}
}

Expand Down
Loading
Loading