Skip to content

Commit 1eaf318

Browse files
authored
[client] fix operation name in the GraphQL request (ExpediaGroup#757)
We were incorrectly specifying normalized operation name to be sent as part of the request instead of passing in the original one from the query. This lead to runtime failures when operation name was not starting with an upper case or was not specified at all. Resolves: ExpediaGroup#756
1 parent 61fb764 commit 1eaf318

File tree

2 files changed

+138
-4
lines changed

2 files changed

+138
-4
lines changed

plugins/graphql-kotlin-plugin-core/src/main/kotlin/com/expediagroup/graphql/plugin/generator/GraphQLClientGenerator.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ class GraphQLClientGenerator(
8080
val fileSpec = FileSpec.builder(packageName = config.packageName, fileName = queryFile.nameWithoutExtension.capitalize())
8181

8282
operationDefinitions.forEach { operationDefinition ->
83-
val operationName = operationDefinition.name ?: queryFile.nameWithoutExtension.capitalize()
84-
val operationTypeName = operationName.capitalize()
83+
val operationTypeName = operationDefinition.name?.capitalize() ?: queryFile.nameWithoutExtension.capitalize()
8584
val context = GraphQLClientGeneratorContext(
8685
packageName = config.packageName,
8786
graphQLSchema = graphQLSchema,
@@ -109,8 +108,13 @@ class GraphQLClientGenerator(
109108
"null"
110109
}
111110

112-
val queryConstName = operationName.toUpperUnderscore()
113-
funSpec.addStatement("return graphQLClient.execute($queryConstName, \"$operationTypeName\", $variableCode)")
111+
val queryConstName = operationTypeName.toUpperUnderscore()
112+
val operationName = if (operationDefinition.name != null) {
113+
"\"${operationDefinition.name}\""
114+
} else {
115+
"null"
116+
}
117+
funSpec.addStatement("return graphQLClient.execute($queryConstName, $operationName, $variableCode)")
114118

115119
val gqlCLientClassName = ClassName(LIBRARY_PACKAGE, "GraphQLClient").parameterizedBy(STAR)
116120
operationTypeSpec.primaryConstructor(FunSpec.constructorBuilder()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Copyright 2020 Expedia, Inc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.expediagroup.graphql.plugin.generator.types
18+
19+
import com.expediagroup.graphql.plugin.generator.GraphQLClientGenerator
20+
import com.expediagroup.graphql.plugin.generator.GraphQLClientGeneratorConfig
21+
import com.expediagroup.graphql.plugin.generator.testSchema
22+
import com.expediagroup.graphql.plugin.generator.verifyGeneratedFileSpecContents
23+
import org.junit.jupiter.api.Test
24+
import org.junit.jupiter.api.io.TempDir
25+
import java.io.File
26+
import java.nio.file.Path
27+
import kotlin.test.assertEquals
28+
29+
class GenerateGraphQLClientIT {
30+
31+
@Test
32+
fun `verify generated client does not change the operation name`() {
33+
val expectedQueryFileSpec = """
34+
package com.expediagroup.graphql.plugin.generator.integration
35+
36+
import com.expediagroup.graphql.client.GraphQLClient
37+
import com.expediagroup.graphql.types.GraphQLResponse
38+
import kotlin.String
39+
40+
const val MI_XE_DCA_SE_QUERY: String = "query miXEDcaSEQuery {\n scalarQuery {\n name\n }\n}"
41+
42+
class MiXEDcaSEQuery(
43+
private val graphQLClient: GraphQLClient<*>
44+
) {
45+
suspend fun execute(): GraphQLResponse<MiXEDcaSEQuery.Result> =
46+
graphQLClient.execute(MI_XE_DCA_SE_QUERY, "miXEDcaSEQuery", null)
47+
48+
/**
49+
* Wrapper that holds all supported scalar types
50+
*/
51+
data class ScalarWrapper(
52+
/**
53+
* UTF-8 character sequence
54+
*/
55+
val name: String
56+
)
57+
58+
data class Result(
59+
/**
60+
* Query that returns wrapper object with all supported scalar types
61+
*/
62+
val scalarQuery: MiXEDcaSEQuery.ScalarWrapper
63+
)
64+
}
65+
""".trimIndent()
66+
67+
val query = """
68+
query miXEDcaSEQuery {
69+
scalarQuery {
70+
name
71+
}
72+
}
73+
""".trimIndent()
74+
verifyGeneratedFileSpecContents(query, expectedQueryFileSpec)
75+
}
76+
77+
@Test
78+
fun `verify generated client does not require operation name`(@TempDir tempDir: Path) {
79+
val expectedQueryFileSpec = """
80+
package com.expediagroup.graphql.plugin.generator.integration
81+
82+
import com.expediagroup.graphql.client.GraphQLClient
83+
import com.expediagroup.graphql.types.GraphQLResponse
84+
import kotlin.String
85+
86+
const val ANONYMOUS_TEST_QUERY: String = "query {\n scalarQuery {\n name\n }\n}"
87+
88+
class AnonymousTestQuery(
89+
private val graphQLClient: GraphQLClient<*>
90+
) {
91+
suspend fun execute(): GraphQLResponse<AnonymousTestQuery.Result> =
92+
graphQLClient.execute(ANONYMOUS_TEST_QUERY, null, null)
93+
94+
/**
95+
* Wrapper that holds all supported scalar types
96+
*/
97+
data class ScalarWrapper(
98+
/**
99+
* UTF-8 character sequence
100+
*/
101+
val name: String
102+
)
103+
104+
data class Result(
105+
/**
106+
* Query that returns wrapper object with all supported scalar types
107+
*/
108+
val scalarQuery: AnonymousTestQuery.ScalarWrapper
109+
)
110+
}
111+
""".trimIndent()
112+
113+
val query = """
114+
query {
115+
scalarQuery {
116+
name
117+
}
118+
}
119+
""".trimIndent()
120+
val testDirectory = tempDir.toFile()
121+
val queryFile = File(testDirectory, "anonymousTestQuery.graphql")
122+
queryFile.deleteOnExit()
123+
queryFile.writeText(query)
124+
125+
val generator = GraphQLClientGenerator(testSchema(), GraphQLClientGeneratorConfig(packageName = "com.expediagroup.graphql.plugin.generator.integration"))
126+
val fileSpecs = generator.generate(listOf(queryFile))
127+
assertEquals(1, fileSpecs.size)
128+
assertEquals(expectedQueryFileSpec, fileSpecs[0].toString().trim())
129+
}
130+
}

0 commit comments

Comments
 (0)