@@ -46,8 +46,6 @@ class CustomScalarInputTest {
4646 opaqueOnly: event(input: { opaque: "alone" })
4747 variable: event(input: ${' $' } event)
4848 file: event(input: { file: ${' $' } file })
49- boxOfText: event(input: { box: "text", date: "2020-01-02" })
50- boxOfDate: event(input: { box: "date:2021-03-04" })
5149 events(inputs: [{ date: "2020-01-02" }, { opaque: "second" }])
5250 optionalEvent(input: { date: "2020-01-02", opaque: "optional" })
5351 message(input: { name: "greeting", file: ${' $' } file, files: ${' $' } files })
@@ -58,14 +56,11 @@ class CustomScalarInputTest {
5856 """
5957 }
6058
61- // a box of text converts, so only the date is embedded, but the box of a date after it has to be embedded too
6259 assertEquals(data - " opaqueLabel" , mapOf (
6360 " literal" to " 2020-01-02 literal" ,
6461 " opaqueOnly" to " alone" ,
6562 " variable" to " 2021-03-04 variable" ,
6663 " file" to " a.txt: Hello" ,
67- " boxOfText" to " 2020-01-02 text" ,
68- " boxOfDate" to " 2021-03-04" ,
6964 " events" to listOf (" 2020-01-02" , " second" ),
7065 " optionalEvent" to " 2020-01-02 optional" ,
7166 " message" to " greeting: Hello big world" ,
@@ -149,8 +144,10 @@ class CustomScalarInputTest {
149144 val data = assertNoGraphQlErrors(graphQL(inputSchema)) {
150145 """
151146 query {
152- payment(input: { price: "5", reference: "ref", location: "1.5,2.5" })
153- withDate: payment(input: { price: "5", reference: "ref", location: "1.5,2.5", date: "2020-01-02" })
147+ payment(input: { price: "5", reference: "ref", box: "text" })
148+ withDate: payment(input: { price: "5", reference: "ref", box: "text", date: "2020-01-02" })
149+ boxOfDate: payment(input: { box: "date:2021-03-04" })
150+ afterBoxOfDate: payment(input: { price: "5", reference: "ref", box: "text", date: "2020-01-02" })
154151 priceNode(input: { price: "5" })
155152 price(price: "5")
156153 }
@@ -164,9 +161,13 @@ class CustomScalarInputTest {
164161 """
165162 }
166163
164+ // a box of a date can't be converted, so the deserializer gets it embedded and has no serialized form to read.
165+ // That doesn't change how a later box of text is read
167166 assertEquals(data, mapOf (
168- " payment" to " MoneyDto(amount=5, currency=CAD) OpaqueDto(value=ref) GeoPoint(lat=1.5, lng=2.5) null" ,
169- " withDate" to " MoneyDto(amount=5, currency=CAD) OpaqueDto(value=ref) GeoPoint(lat=1.5, lng=2.5) 2020-01-02" ,
167+ " payment" to " MoneyDto(amount=5, currency=CAD) OpaqueDto(value=ref) text" ,
168+ " withDate" to " MoneyDto(amount=5, currency=CAD) OpaqueDto(value=ref) 2020-01-02 text" ,
169+ " boxOfDate" to " <missing>" ,
170+ " afterBoxOfDate" to " MoneyDto(amount=5, currency=CAD) OpaqueDto(value=ref) 2020-01-02 text" ,
170171 " priceNode" to """ {"price":{"amount":5,"currency":"CAD"}}""" ,
171172 " price" to " MoneyDto(amount=5, currency=CAD)"
172173 ))
@@ -190,7 +191,7 @@ class CustomScalarInputTest {
190191 private fun graphQL (schema : String , options : SchemaParserOptions = SchemaParserOptions .defaultOptions()): GraphQL {
191192 val graphQLSchema = SchemaParser .newParser()
192193 .schemaString(schema)
193- .scalars(localDateScalar, opaqueScalar, boxScalar, moneyScalar, geoPointScalar, customScalarUUID, uploadScalar)
194+ .scalars(localDateScalar, opaqueScalar, boxScalar, moneyScalar, customScalarUUID, uploadScalar)
194195 .resolvers(resolver)
195196 .options(options)
196197 .build()
@@ -203,7 +204,6 @@ class CustomScalarInputTest {
203204 scalar Opaque
204205 scalar Box
205206 scalar Money
206- scalar GeoPoint
207207 scalar Upload
208208
209209 type Query {
@@ -221,7 +221,6 @@ class CustomScalarInputTest {
221221 input EventInput {
222222 date: LocalDate
223223 opaque: Opaque
224- box: Box
225224 file: Upload
226225 }
227226
@@ -245,8 +244,8 @@ class CustomScalarInputTest {
245244 input PaymentInput {
246245 price: Money
247246 reference: Opaque
248- location: GeoPoint
249247 date: LocalDate
248+ box: Box
250249 }
251250 """
252251
@@ -265,15 +264,15 @@ class CustomScalarInputTest {
265264 val received = mutableMapOf<String , Any >()
266265
267266 fun event (input : EventInput ): String =
268- listOfNotNull(input.date, input.opaque?.value, input.box?.content, input. file?.let { " ${it.name} : ${it.content()} " }).joinToString(" " )
267+ listOfNotNull(input.date, input.opaque?.value, input.file?.let { " ${it.name} : ${it.content()} " }).joinToString(" " )
269268
270269 fun events (inputs : List <EventInput >): List <String > = inputs.map { event(it) }
271270 fun optionalEvent (input : Optional <EventInput >): String = input.map { event(it) }.orElse(" empty" )
272271 fun message (input : MessageInput ): String = " ${input.name} : ${(listOfNotNull(input.file) + input.files).joinToString(" " ) { it.content() }} "
273272 fun label (input : LabelInput ): String = " ${input.date} ${input.opaque} "
274273 fun dateNode (input : ObjectNode ): String = (input[" date" ] as POJONode ).pojo.let { " ${it.javaClass.simpleName} $it " }
275274 fun priceNode (input : ObjectNode ): String = input.toString()
276- fun payment (input : PaymentInput ): String = " ${ input.price} ${ input.reference} ${ input.location} ${ input.date} "
275+ fun payment (input : PaymentInput ): String = listOfNotNull( input.price, input.reference, input.date, input.box).joinToString( " " )
277276 fun price (price : MoneyDto ): String = price.toString()
278277
279278 fun map (input : Map <String , Any ?>) = receive(" map" , input)
@@ -294,7 +293,6 @@ class CustomScalarInputTest {
294293 class EventInput {
295294 var date: LocalDate ? = null
296295 var opaque: Opaque ? = null
297- var box: Box ? = null
298296 var file: Part ? = null
299297 }
300298
@@ -305,10 +303,10 @@ class CustomScalarInputTest {
305303 class PaymentInput {
306304 var price: MoneyDto ? = null
307305 var reference: OpaqueDto ? = null
308-
309- @field:JsonDeserialize(using = GeoPointDeserializer ::class )
310- var location: GeoPoint ? = null
311306 var date: LocalDate ? = null
307+
308+ @field:JsonDeserialize(using = BoxContentDeserializer ::class )
309+ var box: String? = null
312310 }
313311
314312 // serialized as {"value": ...}, which Jackson can't create it from, like the coerced values of many custom scalars
@@ -322,16 +320,13 @@ class CustomScalarInputTest {
322320
323321 data class MoneyDto (val amount : Int , val currency : String )
324322
323+ // only converts if its content does
325324 data class Box (val content : Any )
326325
327- data class GeoPoint (val lat : Double , val lng : Double )
328-
329- // reads the serialized form, and an embedded GeoPoint wouldn't fail it
330- class GeoPointDeserializer : StdDeserializer <GeoPoint >(GeoPoint : :class.java) {
331- override fun deserialize (p : JsonParser , context : DeserializationContext ): GeoPoint {
332- val node = p.codec.readTree<JsonNode >(p)
333- return GeoPoint (node.path(" lat" ).asDouble(), node.path(" lng" ).asDouble())
334- }
326+ // reads the serialized form, and an embedded Box wouldn't fail it
327+ class BoxContentDeserializer : StdDeserializer <String >(String : :class.java) {
328+ override fun deserialize (p : JsonParser , context : DeserializationContext ): String =
329+ p.codec.readTree<JsonNode >(p).path(" content" ).textValue() ? : " <missing>"
335330 }
336331
337332 class NextDayDeserializer : StdDeserializer <LocalDate >(LocalDate : :class.java) {
@@ -359,7 +354,6 @@ class CustomScalarInputTest {
359354 private val opaqueScalar = scalar(" Opaque" ) { Opaque (it) }
360355 private val boxScalar = scalar(" Box" ) { Box (if (it.startsWith(" date:" )) LocalDate .parse(it.removePrefix(" date:" )) else it) }
361356 private val moneyScalar = scalar(" Money" ) { Money (it.toInt(), " CAD" ) }
362- private val geoPointScalar = scalar(" GeoPoint" ) { value -> value.split(" ," ).map { it.toDouble() }.let { GeoPoint (it[0 ], it[1 ]) } }
363357
364358 private fun <T : Any > scalar (name : String , parse : (String ) -> T ): GraphQLScalarType = GraphQLScalarType .newScalar()
365359 .name(name)
0 commit comments