diff --git a/src/main/kotlin/com/github/pgutkowski/kgraphql/request/RequestPreProcessing.kt b/src/main/kotlin/com/github/pgutkowski/kgraphql/request/RequestPreProcessing.kt index 6cf135c2..f3fa9e98 100644 --- a/src/main/kotlin/com/github/pgutkowski/kgraphql/request/RequestPreProcessing.kt +++ b/src/main/kotlin/com/github/pgutkowski/kgraphql/request/RequestPreProcessing.kt @@ -17,8 +17,13 @@ fun tokenizeRequest(input : String) : List { when(input[i]){ in IGNORED_CHARACTERS -> { i++ } in OPERANDS -> { - tokens.add(input[i].toString()) - i++ + if (input.length > i+1 && input.substring(i, i+2) == "]!") { + tokens.add("]!") + i += 2 + } else { + tokens.add(input[i].toString()) + i++ + } } '\"' -> { val substring = input.substring(i + 1) @@ -167,8 +172,8 @@ private fun parseOperationVariables(variablesTokens: List): MutableList< } variableName == null -> variableName = variableToken variableType == null -> variableType = variableToken - variableType.startsWith("[") && variableType == "]" -> variableType += variableToken - variableType.startsWith("[") -> variableType += variableToken + variableType.startsWith(("[")) && variableToken.startsWith("]") -> variableType += variableToken + variableType.startsWith("[") && !variableType.contains("]") -> variableType += variableToken defaultTypeStarted && variableDefaultValue == null -> variableDefaultValue = variableToken else -> { //if variableName of variableType would be null, it would already be matched diff --git a/src/test/kotlin/com/github/pgutkowski/kgraphql/TestClasses.kt b/src/test/kotlin/com/github/pgutkowski/kgraphql/TestClasses.kt index d4e37e66..2676ac77 100644 --- a/src/test/kotlin/com/github/pgutkowski/kgraphql/TestClasses.kt +++ b/src/test/kotlin/com/github/pgutkowski/kgraphql/TestClasses.kt @@ -9,6 +9,9 @@ abstract class Person(val name: String, val age: Int) class Director(name : String, age: Int, val favActors: List) : Person(name, age) +class ActorInput(val name: String, val age: Int) +class ActorCalculateAgeInput(val name: String, val ages: List) + class Actor(name : String, age: Int) : Person(name, age) class Id(val literal: String, val numeric: Int) diff --git a/src/test/kotlin/com/github/pgutkowski/kgraphql/integration/BaseSchemaTest.kt b/src/test/kotlin/com/github/pgutkowski/kgraphql/integration/BaseSchemaTest.kt index 8a6075c6..be347fa6 100644 --- a/src/test/kotlin/com/github/pgutkowski/kgraphql/integration/BaseSchemaTest.kt +++ b/src/test/kotlin/com/github/pgutkowski/kgraphql/integration/BaseSchemaTest.kt @@ -1,17 +1,6 @@ package com.github.pgutkowski.kgraphql.integration -import com.github.pgutkowski.kgraphql.Actor -import com.github.pgutkowski.kgraphql.Director -import com.github.pgutkowski.kgraphql.Film -import com.github.pgutkowski.kgraphql.FilmType -import com.github.pgutkowski.kgraphql.Id -import com.github.pgutkowski.kgraphql.IdScalarSupport -import com.github.pgutkowski.kgraphql.Person -import com.github.pgutkowski.kgraphql.Scenario -import com.github.pgutkowski.kgraphql.defaultSchema -import com.github.pgutkowski.kgraphql.deserialize -import com.github.pgutkowski.kgraphql.schema.DefaultSchema -import com.github.pgutkowski.kgraphql.schema.dsl.SchemaBuilder +import com.github.pgutkowski.kgraphql.* import org.junit.After @@ -184,6 +173,30 @@ abstract class BaseSchemaTest { actor } } + mutation("createActorWithInput") { + description = "create new actor" + resolver { input: ActorInput -> + val actor = Actor(input.name, input.age) + createdActors.add(actor) + actor + } + } + mutation("createActorWithAges") { + description = "create new actor" + resolver { name: String, ages: List -> + val actor = Actor(name, ages.reduce { sum, age -> sum + age }) + createdActors.add(actor) + actor + } + } + mutation("createActorWithAgesInput") { + description = "create new actor" + resolver { input: ActorCalculateAgeInput -> + val actor = Actor(input.name, input.ages.reduce { sum, age -> sum + age }) + createdActors.add(actor) + actor + } + } query("scenario") { resolver { -> Scenario(Id("GKalus", 234234), "Gamil Kalus", "Very long scenario") } } diff --git a/src/test/kotlin/com/github/pgutkowski/kgraphql/request/RequestTokenizationTest.kt b/src/test/kotlin/com/github/pgutkowski/kgraphql/request/RequestTokenizationTest.kt index fd8063fc..c8c4b144 100644 --- a/src/test/kotlin/com/github/pgutkowski/kgraphql/request/RequestTokenizationTest.kt +++ b/src/test/kotlin/com/github/pgutkowski/kgraphql/request/RequestTokenizationTest.kt @@ -51,6 +51,43 @@ class RequestTokenizationTest { ) } + @Test + fun `Tokenize required list argument`() { + val d = "$" + testTokenization( + input = "mutation create(${d}agesName1: String!, ${d}ages: [String!]!){ createActorWithAges(name: ${d}agesName1, ages: ${d}ages1) { name, age } }", + expected = listOf( + "mutation", + "create", + "(", + "${d}agesName1", + ":", + "String!", + "${d}ages", + ":", + "[", + "String!", + "]!", + ")", + "{", + "createActorWithAges", + "(", + "name", + ":", + "${d}agesName1", + "ages", + ":", + "${d}ages1", + ")", + "{", + "name", + "age", + "}", + "}" + ) + ) + } + @Test fun `tokenize input with quotes`(){ testTokenization( diff --git a/src/test/kotlin/com/github/pgutkowski/kgraphql/specification/language/VariablesSpecificationTest.kt b/src/test/kotlin/com/github/pgutkowski/kgraphql/specification/language/VariablesSpecificationTest.kt index b429ea0f..1981bb7a 100644 --- a/src/test/kotlin/com/github/pgutkowski/kgraphql/specification/language/VariablesSpecificationTest.kt +++ b/src/test/kotlin/com/github/pgutkowski/kgraphql/specification/language/VariablesSpecificationTest.kt @@ -89,4 +89,100 @@ class VariablesSpecificationTest : BaseSchemaTest() { ) } } -} \ No newline at end of file + + @Test + fun `Advanced variables`() { + val d = "$" + val request = """ + mutation MultipleCreate( + ${d}name1: String!, + ${d}age1: Int!, + ${d}name2: String!, + ${d}age2: Int!, + + ${d}input1: ActorInput!, + ${d}input2: ActorInput!, + + ${d}agesName1: String!, + ${d}ages1: [Int!]!, + ${d}agesName2: String!, + ${d}ages2: [Int!]!, + + ${d}agesInput1: ActorCalculateAgeInput!, + ${d}agesInput2: ActorCalculateAgeInput! + ) { + createFirst: createActor(name: ${d}name1, age: ${d}age1) { name, age } + createSecond: createActor(name: ${d}name2, age: ${d}age2) { name, age } + inputFirst: createActorWithInput(input: ${d}input1) { name, age } + inputSecond: createActorWithInput(input: ${d}input2) { name, age } + agesFirst: createActorWithAges(name: ${d}agesName1, ages: ${d}ages1) { name, age } + agesSecond: createActorWithAges(name: ${d}agesName2, ages: ${d}ages2) { name, age } + inputAgesFirst: createActorWithAgesInput(input: ${d}agesInput1) { name, age } + inputAgesSecond: createActorWithAgesInput(input: ${d}agesInput2) { name, age } + } + """.trimEnd() + val variables = """ + { + "name1": "Jógvan", + "age1": 1, + "name2": "Paweł", + "age2": 2, + + "input1": {"name": "Olsen", "age": 3}, + "input2": {"name": "Gutkowski", "age": 4}, + + "agesName1": "Someone", + "ages1": [10,50], + "agesName2": "Some other", + "ages2": [5, 10], + + "agesInput1": {"name": "Jógvan Olsen", "ages": [3]}, + "agesInput2": {"name": "Paweł Gutkowski", "ages": [4,5,6,7]} + } + """.trimIndent() + + val result = execute(request, variables) + + + assertNoErrors(result) + assertThat(result.extract("data/createFirst/name"), equalTo("Jógvan")) + assertThat(result.extract("data/createSecond/age"), equalTo(2)) + assertThat(result.extract("data/inputFirst/name"), equalTo("Olsen")) + assertThat(result.extract("data/inputSecond/age"), equalTo(4)) + assertThat(result.extract("data/agesFirst/name"), equalTo("Someone")) + assertThat(result.extract("data/agesSecond/age"), equalTo(15)) + assertThat(result.extract("data/inputAgesFirst/name"), equalTo("Jógvan Olsen")) + assertThat(result.extract("data/inputAgesSecond/age"), equalTo(22)) + } + + @Test + fun `required variable arrays`() { + val d = "$" + val request = """ + mutation MultipleCreate( + ${d}agesName1: String!, + ${d}ages1: [Int!]!, + ${d}agesName2: String!, + ${d}ages2: [Int!]! + ) { + agesFirst: createActorWithAges(name: ${d}agesName1, ages: ${d}ages1) { name, age } + agesSecond: createActorWithAges(name: ${d}agesName2, ages: ${d}ages2) { name, age } + } + """.trimIndent() + val variables = """ + { + "agesName1": "Someone", + "ages1": [10,50], + "agesName2": "Some other", + "ages2": [5, 10] + } + """.trimIndent() + + val result = execute(request, variables) + + + assertNoErrors(result) + assertThat(result.extract("data/agesFirst/name"), equalTo("Someone")) + assertThat(result.extract("data/agesSecond/age"), equalTo(15)) + } +}