├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── other-issue.md
├── dependabot.yml
└── workflows
│ ├── master.yml
│ ├── pull_request.yml
│ └── release.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
├── main
└── java
│ └── graphql
│ └── scalars
│ ├── ExtendedScalars.java
│ ├── alias
│ └── AliasedScalar.java
│ ├── country
│ └── code
│ │ ├── CountryCode.java
│ │ └── CountryCodeScalar.java
│ ├── currency
│ └── CurrencyScalar.java
│ ├── datetime
│ ├── DateScalar.java
│ ├── DateTimeScalar.java
│ ├── LocalTimeCoercing.java
│ └── TimeScalar.java
│ ├── id
│ └── UUIDScalar.java
│ ├── java
│ └── JavaPrimitives.java
│ ├── locale
│ └── LocaleScalar.java
│ ├── numeric
│ ├── FloatCoercing.java
│ ├── IntCoercing.java
│ ├── NegativeFloatScalar.java
│ ├── NegativeIntScalar.java
│ ├── NonNegativeFloatScalar.java
│ ├── NonNegativeIntScalar.java
│ ├── NonPositiveFloatScalar.java
│ ├── NonPositiveIntScalar.java
│ ├── PositiveFloatScalar.java
│ └── PositiveIntScalar.java
│ ├── object
│ ├── JsonScalar.java
│ └── ObjectScalar.java
│ ├── regex
│ └── RegexScalar.java
│ ├── url
│ └── UrlScalar.java
│ └── util
│ └── Kit.java
└── test
└── groovy
└── graphql
└── scalars
├── alias
└── AliasedScalarTest.groovy
├── country
└── code
│ └── CountryCodeScalarTest.groovy
├── currency
└── CurrencyScalarTest.groovy
├── datetime
├── DateScalarTest.groovy
├── DateTimeScalarTest.groovy
├── LocalTimeScalarTest.groovy
└── TimeScalarTest.groovy
├── id
└── UUIDScalarTest.groovy
├── java
├── ScalarsBigDecimalTest.groovy
├── ScalarsBigIntegerTest.groovy
├── ScalarsByteTest.groovy
├── ScalarsCharTest.groovy
├── ScalarsLongTest.groovy
└── ScalarsShortTest.groovy
├── locale
└── LocaleScalarTest.groovy
├── numeric
├── NegativeFloatScalarTest.groovy
├── NegativeIntScalarTest.groovy
├── NonNegativeFloatScalarTest.groovy
├── NonNegativeIntScalarTest.groovy
├── NonPositiveFloatScalarTest.groovy
├── NonPositiveIntScalarTest.groovy
├── PositiveFloatScalarTest.groovy
└── PositiveIntScalarTest.groovy
├── object
└── ObjectScalarTest.groovy
├── regex
└── RegexScalarTest.groovy
├── url
└── UrlScalarTest.groovy
└── util
└── TestKit.groovy
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Please provide a code example or even better a test to reproduce the bug.
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/other-issue.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Other issue
3 | about: Generic issue
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | If you have a general question or seeking advice how to use something please create a new topic in our GitHub discussions forum: https://github.com/graphql-java/graphql-java/discussions. Thanks.
11 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "gradle"
4 | directory: "/"
5 | schedule:
6 | interval: "weekly"
7 | - package-ecosystem: "github-actions"
8 | directory: "/"
9 | schedule:
10 | interval: "weekly"
11 |
--------------------------------------------------------------------------------
/.github/workflows/master.yml:
--------------------------------------------------------------------------------
1 | name: Master Build and Publish
2 | # For master push: Builds and publishes the development version to bintray/maven
3 | on:
4 | push:
5 | branches:
6 | - master
7 | jobs:
8 | buildAndPublish:
9 | runs-on: ubuntu-latest
10 | env:
11 | MAVEN_CENTRAL_USER: ${{ secrets.MAVEN_CENTRAL_USER }}
12 | MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
13 | MAVEN_CENTRAL_PGP_KEY: ${{ secrets.MAVEN_CENTRAL_PGP_KEY }}
14 |
15 | steps:
16 | - uses: actions/checkout@v4
17 | - uses: gradle/wrapper-validation-action@v3
18 | - name: Set up JDK 11
19 | uses: actions/setup-java@v4
20 | with:
21 | java-version: '11'
22 | distribution: 'corretto'
23 | - name: build test and publish
24 | run: ./gradlew assemble && ./gradlew check --info && ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository -x check --info --stacktrace
25 |
--------------------------------------------------------------------------------
/.github/workflows/pull_request.yml:
--------------------------------------------------------------------------------
1 | name: Pull Request Build
2 | # For pull requests: builds and test
3 | on:
4 | push:
5 | branches:
6 | - '!master'
7 | pull_request:
8 | branches:
9 | - master
10 | - 20.x
11 | - 19.x
12 | - 18.x
13 | jobs:
14 | buildAndTest:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v4
18 | - uses: gradle/wrapper-validation-action@v3
19 | - name: Set up JDK 11
20 | uses: actions/setup-java@v4
21 | with:
22 | java-version: '11'
23 | distribution: 'corretto'
24 | - name: build and test
25 | run: ./gradlew assemble && ./gradlew check --info --stacktrace
26 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Manual Release Build
2 | # Release builds
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | version:
7 | description: 'the version to be released'
8 | required: true
9 |
10 | jobs:
11 | buildAndPublish:
12 | runs-on: ubuntu-latest
13 | env:
14 | MAVEN_CENTRAL_PGP_KEY: ${{ secrets.MAVEN_CENTRAL_PGP_KEY }}
15 | MAVEN_CENTRAL_USER: ${{ secrets.MAVEN_CENTRAL_USER }}
16 | MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
17 | RELEASE_VERSION: ${{ github.event.inputs.version }}
18 |
19 | steps:
20 | - uses: actions/checkout@v4
21 | - uses: gradle/wrapper-validation-action@v3
22 | - name: Set up JDK 11
23 | uses: actions/setup-java@v4
24 | with:
25 | java-version: '11'
26 | distribution: 'corretto'
27 | - name: build test and publish
28 | run: ./gradlew assemble && ./gradlew check --info && ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository -x check --info --stacktrace
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .gradle
3 | out
4 | *.iml
5 |
6 | build
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Brad Baker and Contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
6 | (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge,
7 | publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do
8 | so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
13 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
14 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
15 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Extended Scalars for graphql-java
2 |
3 | [](https://github.com/graphql-java/graphql-java-extended-scalars/actions/workflows/master.yml)
4 | [](https://maven-badges.herokuapp.com/maven-central/com.graphql-java/graphql-java-extended-scalars/)
5 | [](https://maven-badges.herokuapp.com/maven-central/com.graphql-java/graphql-java-extended-scalars/)
6 | [](https://github.com/graphql-java/graphql-java-extended-scalars/blob/master/LICENSE.md)
7 |
8 | ## Overview
9 |
10 | This library provides extended scalars for [graphql-java](https://github.com/graphql-java/graphql-java)
11 |
12 | [GraphQL Scalars](https://spec.graphql.org/draft/#sec-Scalars) are the primitive leaf values in the GraphQL type system which cannot be queried further via sub-field selections.
13 |
14 | The GraphQL Specification defines `String`, `Int`, `Float`, `Boolean` and `ID` as well-defined [built-in scalars](https://spec.graphql.org/draft/#sec-Scalars.Built-in-Scalars) that must be present in a graphql type
15 | system. Beyond these, it is up to an implementation to decide what [custom scalars](https://spec.graphql.org/draft/#sec-Scalars.Custom-Scalars) are present.
16 |
17 | You would use custom scalars when you want to describe more meaningful behavior or ranges of values.
18 |
19 | # Getting started
20 |
21 | ## How to install
22 |
23 | To use this library put the following into your gradle config
24 |
25 | ```java
26 | implementation 'com.graphql-java:graphql-java-extended-scalars:22.0'
27 | ```
28 |
29 | or the following into your Maven config
30 |
31 | ```xml
32 |
33 | com.graphql-java
34 | graphql-java-extended-scalars
35 | 22.0
36 |
37 | ```
38 |
39 | > Note:
40 | >
41 | > use 22.0 or above for graphql-java 22.x and above
42 | >
43 | > use 21.0 for graphql-java 21.x
44 | >
45 | > use 20.2 for graphql-java 20.x
46 | >
47 |
48 | ## How to use extended scalars
49 |
50 | ### Direct use
51 |
52 | Register the scalar with `graphql-java`
53 |
54 | ```java
55 | RuntimeWiring.newRuntimeWiring().scalar(ExtendedScalars.DateTime)
56 | ```
57 |
58 | ### Spring for GraphQL
59 |
60 | If you are using [Spring for GraphQL](https://docs.spring.io/spring-graphql/docs/current/reference/html/), register the scalar with `RuntimeWiringConfigurer`
61 |
62 | ```java
63 | @Configuration
64 | public class GraphQlConfig {
65 | @Bean
66 | public RuntimeWiringConfigurer runtimeWiringConfigurer() {
67 | return wiringBuilder -> wiringBuilder.scalar(ExtendedScalars.DateTime);
68 | }
69 | }
70 | ```
71 |
72 | ### Netflix DGS
73 |
74 | Note: Netflix also wraps this library in `com.netflix.graphql.dgs:graphql-dgs-extended-scalars` for [automatic registration](https://netflix.github.io/dgs/scalars/#automatically-register-scalar-extensions-via-graphql-dgs-extended-scalars).
75 |
76 | If you are using [Netflix DGS](https://netflix.github.io/dgs), please see the following docs:
77 | - [registration through runtime wiring](https://netflix.github.io/dgs/scalars/#register-scalar-extensions-via-dgsruntimewiring)
78 | - [configuration documentation](https://netflix.github.io/dgs/configuration/#dgs-extended-scalars-graphql-dgs-extended-scalars)
79 |
80 | ## How to add extended scalars to your schema
81 |
82 | The GraphQL Specification recommends the use of the [@specifiedBy](https://spec.graphql.org/October2021/#sec--specifiedBy) built-in schema directive to provide a scalar specification URL for specifying the behavior of custom scalar types.
83 |
84 | ```graphql
85 | directive @specifiedBy(url: String!) on SCALAR
86 | ```
87 |
88 | To use a extended scalar in your schema, define the scalar like shown below for `DateTime`
89 |
90 | ```graphql
91 | scalar DateTime
92 | @specifiedBy(url: "https://scalars.graphql.org/andimarek/date-time.html")
93 |
94 | type Something {
95 | someDateTime: DateTime
96 | }
97 | ```
98 |
99 | # Custom Scalars
100 |
101 | ## Alias Scalars
102 |
103 |
104 |
105 | Scalar Definition
106 | Description
107 |
108 |
109 |
110 | scalar AliasedScalar
111 |
112 | You can create aliases for existing scalars to add more semantic meaning to them.
113 |
114 |
115 |
116 | For example a link to a social media post could be representing by a `String` but the name `SocialMediaLink` is a
117 | more semantically meaningful name for that scalar type.
118 |
119 | For example, you would build it like this:
120 |
121 | ```java
122 | AliasedScalar socialMediaLink = ExtendedScalars.newAliasedScalar("SocialMediaLink")
123 | .aliasedScalar(Scalars.GraphQLString)
124 | .build()
125 | ```
126 |
127 | And use it in a SDL schema like this :
128 |
129 | ```graphql
130 | type Customer {
131 | name: String
132 | socialMediaLink: SocialMediaLink
133 | }
134 | ```
135 |
136 | ## Date & Time Scalars
137 |
138 |
139 |
140 | Scalar Definition
141 | Description
142 |
143 |
144 |
145 | scalar DateTime
146 | @specifiedBy(url:
147 | "https://scalars.graphql.org/andimarek/date-time.html"
148 | )
149 |
150 | A RFC-3339 compliant date time scalar that accepts string values like 1996-12-19T16:39:57-08:00
and produces java.time.OffsetDateTime
objects at runtime.
151 |
152 |
153 |
154 | scalar Date
155 | @specifiedBy(url:
156 | "https://tools.ietf.org/html/rfc3339"
157 | )
158 | A RFC-3339 compliant date scalar that accepts string values like 1996-12-19
and produces java.time.LocalDate
objects at runtime.
159 |
160 |
161 |
162 | scalar Time
163 | @specifiedBy(url:
164 | "https://tools.ietf.org/html/rfc3339"
165 | )
166 |
167 | A RFC-3339 compliant time scalar that accepts string values like 16:39:57-08:00
and produces java.time.OffsetTime
objects at runtime.
168 |
169 |
170 |
171 | scalar LocalTime
172 |
173 | 24-hour clock time string in the format hh:mm:ss.sss
or hh:mm:ss
if partial seconds is zero and produces java.time.LocalTime
objects at runtime.
174 |
175 |
176 |
177 | An example declaration in SDL might be:
178 |
179 | ```graphql
180 | type Customer {
181 | birthDay: Date
182 | workStartTime: Time
183 | bornAt: DateTime
184 | }
185 |
186 | type Query {
187 | customers(bornAfter: DateTime): [Customers]
188 | }
189 | ```
190 |
191 | And example query might look like:
192 |
193 | ```graphql
194 | query {
195 | customers(bornAfter: "1996-12-19T16:39:57-08:00") {
196 | birthDay
197 | bornAt
198 | }
199 | }
200 | ```
201 |
202 | ## ID Scalars
203 |
204 |
205 |
206 | Scalar Definition
207 | Description
208 |
209 |
210 |
211 | scalar UUID
212 | @specifiedBy(url:
213 | "https://tools.ietf.org/html/rfc4122"
214 | )
215 |
216 | A universally unique identifier scalar that accepts uuid values like 2423f0a0-3b81-4115-a189-18df8b35e8fc
and produces java.util.UUID
instances at runtime.
217 |
218 |
219 |
220 | ## Numeric Scalars
221 |
222 |
223 |
224 | Scalar Definition
225 | Description
226 |
227 |
228 | scalar PositiveInt
229 | An Int
scalar that MUST be greater than zero.
230 |
231 |
232 | scalar NegativeInt
233 | An Int
scalar that MUST be less than zero.
234 |
235 |
236 | scalar NonPositiveInt
237 | An Int
scalar that MUST be less than or equal to zero.
238 |
239 |
240 | scalar NonNegativeInt
241 | An Int
scalar that MUST be greater than or equal to zero.
242 |
243 |
244 | scalar PositiveFloat
245 | An Float
scalar that MUST be greater than zero.
246 |
247 |
248 | scalar NegativeFloat
249 | An Float
scalar that MUST be less than zero.
250 |
251 |
252 | scalar NonPositiveFloat
253 | An Float
scalar that MUST be less than or equal to zero.
254 |
255 |
256 | scalar NonNegativeFloat
257 | An Float
scalar that MUST be greater than or equal to zero.
258 |
259 |
260 |
261 | The numeric scalars are derivations of the standard GraphQL `Int` and `Float` scalars that enforce range limits.
262 |
263 | An example declaration in SDL might be:
264 |
265 | ```graphql
266 | type Customer {
267 | name: String
268 | currentHeight: PositiveInt
269 | weightLossGoal: NonPositiveInt
270 | averageWeightLoss: NegativeFloat
271 | }
272 |
273 | type Query {
274 | customers(height: PositiveInt): [Customers]
275 | }
276 | ```
277 |
278 | And example query might look like:
279 |
280 | ```graphql
281 | query {
282 | customers(height: 182) {
283 | name
284 | height
285 | weightLossGoal
286 | }
287 | }
288 | ```
289 |
290 | ## Java Primitives
291 |
292 |
293 |
294 | Scalar Definition
295 | Description
296 |
297 |
298 | scalar GraphQLLong
299 | A scalar which represents java.lang.Long
300 |
301 |
302 | scalar GraphQLShort
303 | A scalar which represents java.lang.Short
304 |
305 |
306 | scalar GraphQLByte
307 | A scalar which represents java.lang.Byte
308 |
309 |
310 | scalar GraphQLBigDecimal
311 | A scalar which represents java.math.BigDecimal
312 |
313 |
314 | scalar GraphQLBigInteger
315 | A scalar which represents java.math.BigInteger
316 |
317 |
318 | scalar GraphQLChar
319 | A scalar which represents java.lang.Character
320 |
321 |
322 |
323 | ## Locale Scalar
324 |
325 |
326 |
327 | Scalar Definition
328 | Description
329 |
330 |
331 |
332 | scalar Locale
333 | @specifiedBy(url:
334 | "https://tools.ietf.org/html/bcp47"
335 | )
336 |
337 | The Locale scalar handles IETF BCP 47 language tags via the JDK method Locale.forLanguageTag .
338 |
339 |
340 |
341 | ```graphql
342 | type Customer {
343 | name: String
344 | locale: Locale
345 | }
346 |
347 | type Query {
348 | customers(inLocale: Locale): [Customers]
349 | }
350 | ```
351 |
352 | An example query to look for customers in the Romanian locale might look like:
353 |
354 | ```graphql
355 | query {
356 | customers(inLocale: "ro-RO") {
357 | name
358 | locale
359 | }
360 | }
361 | ```
362 |
363 | ## Country Code Scalar
364 |
365 |
366 |
367 | Scalar Definition
368 | Description
369 |
370 |
371 |
372 | scalar CountryCode
373 | @specifiedBy(url:
374 | "https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2"
375 | )
376 |
377 | The CountryCode scalar type as defined by ISO 3166-1 alpha-2 .
378 |
379 |
380 |
381 | An example declaration in SDL might be:
382 |
383 | ```graphql
384 | scalar CountryCode
385 |
386 | type Customer {
387 | name: String
388 | countryCode: CountryCode
389 | }
390 | ```
391 |
392 | And example query might look like:
393 |
394 | ```graphql
395 | query {
396 | customers(code: "US") {
397 | name
398 | countryCode
399 | }
400 | }
401 | ```
402 |
403 | ## Currency Scalar
404 |
405 |
406 |
407 | Scalar Definition
408 | Description
409 |
410 |
411 |
412 | scalar Currency
413 | @specifiedBy(url:
414 | "https://en.wikipedia.org/wiki/ISO_4217"
415 | )
416 |
417 | A field whose value is an ISO-4217 currency.
418 |
419 |
420 |
421 | An example declaration in SDL might be:
422 |
423 | ```graphql
424 | scalar Currency
425 |
426 | type Account {
427 | id: String
428 | currency: Currency
429 | accountNumber: String
430 | }
431 | ```
432 |
433 | And example query might look like:
434 |
435 | ```graphql
436 | query {
437 | accounts(currency: "USD") {
438 | id
439 | currency
440 | accountNumber
441 | }
442 | }
443 | ```
444 |
445 | ## URL Scalars
446 |
447 |
448 |
449 | Scalar Definition
450 | Description
451 |
452 |
453 |
454 | scalar URL
455 | @specifiedBy(url:
456 | "https://www.w3.org/Addressing/URL/url-spec.txt"
457 | )
458 |
459 | An url scalar that accepts string values like https://www.w3.org/Addressing/URL/url-spec.txt and produces java.net.URL
objects at runtime.
460 |
461 |
462 |
463 | ## Object / JSON Scalars
464 |
465 |
466 |
467 | Scalar Definition
468 | Description
469 |
470 |
471 | scalar Object
472 | An object scalar that accepts any object as a scalar value.
473 |
474 |
475 | scalar JSON
476 | A synonym for the Object
scalar, it will accept any object as a scalar value.
477 |
478 |
479 |
480 | One of the design goals of GraphQL, is that the type system describes the shape of the data returned.
481 |
482 | The `Object` / `JSON` scalars work against this some what because they can return compound values outside the type system. As such
483 | they should be used sparingly. In general your should aim to describe the data via the GraphQL type system where you can and only
484 | resort to the `Object` / `JSON` scalars in very rare circumstances.
485 |
486 | An example might be an extensible GraphQL system where systems can input custom metadata objects that cant be known at
487 | schema type design time.
488 |
489 | An example declaration in SDL might be:
490 |
491 | ```graphql
492 | type Customer {
493 | name: String
494 | associatedMetaData: JSON
495 | }
496 |
497 | type Query {
498 | customers(filterSyntax: JSON): [Customers]
499 | }
500 | ```
501 |
502 | And example query might look like:
503 |
504 | ```graphql
505 | query {
506 | customers(
507 | filterSyntax: {
508 | startSpan: "First"
509 | matchCriteria: { countryCode: "AU", isoCodes: ["27B-34R", "95A-E23"] }
510 | }
511 | ) {
512 | name
513 | associatedMetaData
514 | }
515 | }
516 | ```
517 |
518 | Note : The `JSON` scalar is a simple alias type to the `Object` scalar because often the returned data is a blob of JSON. They are
519 | all just objects at runtime in `graphql-java` terms and what network serialization protocol is up to you. Choose whichever name you think
520 | adds more semantic readers to your schema consumers.
521 |
522 | ## Regex Scalars
523 |
524 |
525 |
526 | Scalar Name
527 | Description
528 |
529 |
530 | RegexScalar
531 | Allows you to build a new scalar via a builder pattern using regular expressions.
532 |
533 |
534 |
535 | The RegexScalar has a builder where you provide one or more regex patterns that control the acceptable values
536 | for a new scalar.
537 |
538 | You name the scalar and it provides an implementation.
539 |
540 | For example, imagine a `phoneNumber` scalar like this :
541 |
542 | ```java
543 |
544 | RegexScalar phoneNumberScalar = ExtendedScalars.newRegexScalar("phoneNumber")
545 | .addPattern(Pattern.compile("\\([0-9]*\\)[0-9]*"))
546 | .build()
547 |
548 | ```
549 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | import java.text.SimpleDateFormat
2 |
3 |
4 | plugins {
5 | id 'java'
6 | id 'groovy'
7 | id 'java-library'
8 | id 'maven-publish'
9 | id 'signing'
10 | id "io.github.gradle-nexus.publish-plugin" version "2.0.0"
11 | id "biz.aQute.bnd.builder" version "6.4.0"
12 | }
13 |
14 | java {
15 | toolchain {
16 | languageVersion = JavaLanguageVersion.of(11)
17 | }
18 | }
19 |
20 | def getDevelopmentVersion() {
21 | def output = new StringBuilder()
22 | def error = new StringBuilder()
23 | def gitShortHash = "git -C ${projectDir} rev-parse --short HEAD".execute()
24 | gitShortHash.waitForProcessOutput(output, error)
25 | def gitHash = output.toString().trim()
26 | if (gitHash.isEmpty()) {
27 | println "git hash is empty: error: ${error.toString()}"
28 | throw new IllegalStateException("git hash could not be determined")
29 | }
30 | "0.0.0-" + new SimpleDateFormat('yyyy-MM-dd\'T\'HH-mm-ss').format(new Date()) + "-" + gitHash
31 | }
32 |
33 | def releaseVersion = System.env.RELEASE_VERSION
34 | version = releaseVersion ? releaseVersion : getDevelopmentVersion()
35 | println "Building version = " + version
36 | group = 'com.graphql-java'
37 |
38 | repositories {
39 | mavenCentral()
40 | mavenLocal()
41 | }
42 |
43 | dependencies {
44 | implementation "com.graphql-java:graphql-java:22.3"
45 |
46 | testImplementation "org.spockframework:spock-core:2.3-groovy-3.0"
47 | testImplementation "org.codehaus.groovy:groovy:3.0.23"
48 | }
49 |
50 | task sourcesJar(type: Jar, dependsOn: classes) {
51 | archiveClassifier.set("sources")
52 | from sourceSets.main.allSource
53 | }
54 |
55 | task javadocJar(type: Jar, dependsOn: javadoc) {
56 | archiveClassifier.set("javadoc")
57 | from javadoc.destinationDir
58 | }
59 |
60 | artifacts {
61 | archives sourcesJar
62 | archives javadocJar
63 | }
64 |
65 | test {
66 | useJUnitPlatform()
67 | testLogging {
68 | exceptionFormat = 'full'
69 | }
70 | }
71 |
72 | publishing {
73 | publications {
74 | maven(MavenPublication) {
75 | from components.java
76 | groupId group
77 | artifactId 'graphql-java-extended-scalars'
78 | version version
79 |
80 | artifact sourcesJar
81 | artifact javadocJar
82 |
83 | pom.withXml {
84 | asNode().children().last() + {
85 | resolveStrategy = Closure.DELEGATE_FIRST
86 | name 'graphql-java-extended-scalars'
87 | description 'A library of extended scalars for graphql-java'
88 | url 'https://github.com/graphql-java/graphql-java-extended-scalars'
89 | inceptionYear '2018'
90 |
91 | scm {
92 | url 'https://github.com/graphql-java/graphql-java-extended-scalars'
93 | connection 'scm:git@github.com:graphql-java/graphql-java-extended-scalars.git'
94 | developerConnection 'scm:git@github.com:graphql-java/graphql-java-extended-scalars.git'
95 | }
96 |
97 | licenses {
98 | license {
99 | name 'MIT'
100 | url 'https://github.com/graphql-java/graphql-java/blob/master/LICENSE.md'
101 | distribution 'repo'
102 | }
103 | }
104 |
105 | developers {
106 | developer {
107 | id 'bbakerman'
108 | name 'Brad Baker'
109 | email 'bbakerman@gmail.com'
110 | }
111 | }
112 | }
113 | }
114 | }
115 | }
116 | }
117 |
118 | nexusPublishing {
119 | repositories {
120 | sonatype {
121 | username = System.env.MAVEN_CENTRAL_USER
122 | password = System.env.MAVEN_CENTRAL_PASSWORD
123 | }
124 | }
125 | }
126 |
127 | signing {
128 | def signingKey = System.env.MAVEN_CENTRAL_PGP_KEY
129 | useInMemoryPgpKeys(signingKey, "")
130 | sign publishing.publications
131 | }
132 |
133 | // all publish tasks depend on the build task
134 | tasks.withType(PublishToMavenRepository) {
135 | dependsOn build
136 | }
137 |
138 | jar {
139 | manifest {
140 | attributes('Automatic-Module-Name': 'com.graphqljava.extendedscalars',
141 | '-exportcontents': 'graphql.scalars.*',
142 | '-removeheaders': 'Private-Package')
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/graphql-java/graphql-java-extended-scalars/7faaf0b6f11077e28843ab790ecc5096984fbd5c/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'graphql-java-extended-scalars'
2 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/ExtendedScalars.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars;
2 |
3 | import graphql.PublicApi;
4 | import graphql.scalars.alias.AliasedScalar;
5 | import graphql.scalars.country.code.CountryCodeScalar;
6 | import graphql.scalars.currency.CurrencyScalar;
7 | import graphql.scalars.datetime.DateScalar;
8 | import graphql.scalars.datetime.DateTimeScalar;
9 | import graphql.scalars.datetime.LocalTimeCoercing;
10 | import graphql.scalars.datetime.TimeScalar;
11 | import graphql.scalars.java.JavaPrimitives;
12 | import graphql.scalars.locale.LocaleScalar;
13 | import graphql.scalars.id.UUIDScalar;
14 | import graphql.scalars.numeric.NegativeFloatScalar;
15 | import graphql.scalars.numeric.NegativeIntScalar;
16 | import graphql.scalars.numeric.NonNegativeFloatScalar;
17 | import graphql.scalars.numeric.NonNegativeIntScalar;
18 | import graphql.scalars.numeric.NonPositiveFloatScalar;
19 | import graphql.scalars.numeric.NonPositiveIntScalar;
20 | import graphql.scalars.numeric.PositiveFloatScalar;
21 | import graphql.scalars.numeric.PositiveIntScalar;
22 | import graphql.scalars.object.JsonScalar;
23 | import graphql.scalars.object.ObjectScalar;
24 | import graphql.scalars.regex.RegexScalar;
25 | import graphql.scalars.url.UrlScalar;
26 | import graphql.schema.GraphQLScalarType;
27 |
28 | /**
29 | * This is the API entry point for all the extended scalars
30 | */
31 | @PublicApi
32 | public class ExtendedScalars {
33 |
34 | /**
35 | * An RFC-3339 compliant date time scalar that accepts string values like `1996-12-19T16:39:57-08:00` and produces
36 | * `java.time.OffsetDateTime` objects at runtime.
37 | *
38 | * Its {@link graphql.schema.Coercing#serialize(java.lang.Object)} and {@link graphql.schema.Coercing#parseValue(java.lang.Object)} methods
39 | * accept OffsetDateTime, ZoneDateTime and formatted Strings as valid objects.
40 | *
41 | * See the rfc3339 spec for more details on the format.
42 | *
43 | * @see java.time.OffsetDateTime
44 | * @see java.time.ZonedDateTime
45 | */
46 | public static final GraphQLScalarType DateTime = DateTimeScalar.INSTANCE;
47 |
48 | /**
49 | * An RFC-3339 compliant date scalar that accepts string values like `1996-12-19` and produces
50 | * `java.time.LocalDate` objects at runtime.
51 | *
52 | * Its {@link graphql.schema.Coercing#serialize(java.lang.Object)} and {@link graphql.schema.Coercing#parseValue(java.lang.Object)} methods
53 | * accept date {@link java.time.temporal.TemporalAccessor}s and formatted Strings as valid objects.
54 | *
55 | * See the rfc3339 spec for more details on the format.
56 | *
57 | * @see java.time.LocalDate
58 | */
59 | public static final GraphQLScalarType Date = DateScalar.INSTANCE;
60 | /**
61 | * An RFC-3339 compliant time scalar that accepts string values like `6:39:57-08:00` and produces
62 | * `java.time.OffsetTime` objects at runtime.
63 | *
64 | * Its {@link graphql.schema.Coercing#serialize(java.lang.Object)} and {@link graphql.schema.Coercing#parseValue(java.lang.Object)} methods
65 | * accept time {@link java.time.temporal.TemporalAccessor}s and formatted Strings as valid objects.
66 | *
67 | * See the rfc3339 spec for more details on the format.
68 | *
69 | * @see java.time.OffsetTime
70 | */
71 | public static final GraphQLScalarType Time = TimeScalar.INSTANCE;
72 |
73 | /**
74 | * A 24-hour local time scalar that accepts strings like `hh:mm:ss` and `hh:mm:ss.sss` and produces
75 | * `java.time.LocalTime` objects at runtime.
76 | *
77 | * Its {@link graphql.schema.Coercing#serialize(java.lang.Object)} and {@link graphql.schema.Coercing#parseValue(java.lang.Object)} methods
78 | * accept time {@link java.time.temporal.TemporalAccessor}s and formatted Strings as valid objects.
79 | *
80 | * @see java.time.LocalTime
81 | */
82 | public static final GraphQLScalarType LocalTime = GraphQLScalarType.newScalar()
83 | .name("LocalTime")
84 | .description("24-hour clock time value string in the format `hh:mm:ss` or `hh:mm:ss.sss`.")
85 | .coercing(new LocalTimeCoercing())
86 | .build();
87 |
88 | /**
89 | * An object scalar allows you to have a multi level data value without defining it in the graphql schema.
90 | *
91 | * It might be useful when you have opaque data coming from a backend system that you want to pass on
92 | * but cant provide the actual graphql schema definition for.
93 | *
94 | * Use this with caution since is breaks one of the key benefits
95 | * of graphql, which is that a schema describes the shape of the data that can be queried.
96 | *
97 | *
98 | * This can be declared as follows :
99 | *
100 | * {@code
101 | *
102 | * type Customer {
103 | * name : String
104 | * backendDetails : Object
105 | * }
106 | * }
107 | *
108 | *
109 | * @see #Json
110 | */
111 | public static final GraphQLScalarType Object = ObjectScalar.INSTANCE;
112 |
113 | /**
114 | * A synonym class for the {@link #Object} scalar, since some people prefer their SDL to look like the following :
115 | *
116 | *
117 | * {@code
118 | *
119 | * type Customer {
120 | * name : String
121 | * backendDetails : JSON
122 | * }
123 | * }
124 | *
125 | *
126 | * @see graphql.scalars.ExtendedScalars#Object
127 | */
128 | public static final GraphQLScalarType Json = JsonScalar.INSTANCE;
129 |
130 | /**
131 | * A URL scalar that accepts URL strings and produces {@link java.net.URL} objects at runtime
132 | */
133 | public static final GraphQLScalarType Url = UrlScalar.INSTANCE;
134 |
135 | /**
136 | * A Locale scalar that accepts a IETF BCP 47 language tag string and produces {@link
137 | * java.util.Locale} objects at runtime.
138 | */
139 | public static final GraphQLScalarType Locale = LocaleScalar.INSTANCE;
140 |
141 | /**
142 | * A field whose value is an ISO-4217 currency.
143 | * See the ISO-4217 for more details.
144 | */
145 | public static final GraphQLScalarType Currency = CurrencyScalar.INSTANCE;
146 |
147 | /**
148 | * The CountryCode scalar type as defined by ISO 3166-1 alpha-2.
149 | * See the ISO 3166-1 alpha-2 for more details.
150 | */
151 | public static final GraphQLScalarType CountryCode = CountryCodeScalar.INSTANCE;
152 |
153 | /**
154 | * A UUID scalar that accepts a universally unique identifier and produces {@link
155 | * java.util.UUID} objects at runtime.
156 | */
157 | public static final GraphQLScalarType UUID = UUIDScalar.INSTANCE;
158 |
159 | /**
160 | * An `Int` scalar that MUST be greater than zero
161 | *
162 | * @see graphql.Scalars#GraphQLInt
163 | */
164 | public static final GraphQLScalarType PositiveInt = PositiveIntScalar.INSTANCE;
165 | /**
166 | * An `Int` scalar that MUST be less than zero
167 | *
168 | * @see graphql.Scalars#GraphQLInt
169 | */
170 | public static final GraphQLScalarType NegativeInt = NegativeIntScalar.INSTANCE;
171 | /**
172 | * An `Int` scalar that MUST be less than or equal to zero
173 | *
174 | * @see graphql.Scalars#GraphQLInt
175 | */
176 | public static final GraphQLScalarType NonPositiveInt = NonPositiveIntScalar.INSTANCE;
177 | /**
178 | * An `Int` scalar that MUST be greater than or equal to zero
179 | *
180 | * @see graphql.Scalars#GraphQLInt
181 | */
182 | public static final GraphQLScalarType NonNegativeInt = NonNegativeIntScalar.INSTANCE;
183 |
184 | /**
185 | * An `Float` scalar that MUST be greater than zero
186 | *
187 | * @see graphql.Scalars#GraphQLFloat
188 | */
189 | public static final GraphQLScalarType PositiveFloat = PositiveFloatScalar.INSTANCE;
190 | /**
191 | * An `Float` scalar that MUST be less than zero
192 | *
193 | * @see graphql.Scalars#GraphQLFloat
194 | */
195 | public static final GraphQLScalarType NegativeFloat = NegativeFloatScalar.INSTANCE;
196 | /**
197 | * An `Float` scalar that MUST be less than or equal to zero
198 | *
199 | * @see graphql.Scalars#GraphQLFloat
200 | */
201 | public static final GraphQLScalarType NonPositiveFloat = NonPositiveFloatScalar.INSTANCE;
202 | /**
203 | * An `Float` scalar that MUST be greater than or equal to zero
204 | *
205 | * @see graphql.Scalars#GraphQLFloat
206 | */
207 | public static final GraphQLScalarType NonNegativeFloat = NonNegativeFloatScalar.INSTANCE;
208 |
209 |
210 | /**
211 | * A builder of a scalar that uses one or more regular expression {@link java.util.regex.Pattern}s to control
212 | * the acceptable values for that scalar.
213 | *
214 | * The scalar converts any passed in objects to Strings first and them matches it against the provided
215 | * scalars to ensure its an acceptable value.
216 | *
217 | * @param name the name of the scalar
218 | *
219 | * @return a builder of a regex scalar
220 | */
221 | public static RegexScalar.Builder newRegexScalar(String name) {
222 | return new RegexScalar.Builder().name(name);
223 | }
224 |
225 | /**
226 | * This allows an existing scalar to be wrapped and aliased with a new name.
227 | *
228 | * For example you may take a `String` scalar and alias it as `SocialMediaLink` if that helps introduce
229 | * more semantic meaning to your type system.
230 | *
231 | * {@code
232 | *
233 | * type Customer {
234 | * name : String
235 | * socialMediaLink : SocialMediaLink
236 | * }
237 | * }
238 | *
239 | *
240 | * A future version of the graphql specification may add this capability but in the meantime you can use this facility.
241 | *
242 | * @param name the name of the aliased scalar
243 | *
244 | * @return a builder of a aliased scalar
245 | */
246 | public static AliasedScalar.Builder newAliasedScalar(String name) {
247 | return new AliasedScalar.Builder().name(name);
248 | }
249 |
250 | /**
251 | * This represents the "Long" type which is a representation of java.lang.Long
252 | */
253 | public static final GraphQLScalarType GraphQLLong = JavaPrimitives.GraphQLLong;
254 |
255 | /**
256 | * This represents the "Short" type which is a representation of java.lang.Short
257 | */
258 | public static final GraphQLScalarType GraphQLShort = JavaPrimitives.GraphQLShort;
259 |
260 | /**
261 | * This represents the "Byte" type which is a representation of java.lang.Byte
262 | */
263 | public static final GraphQLScalarType GraphQLByte = JavaPrimitives.GraphQLByte;
264 |
265 | /**
266 | * This represents the "BigDecimal" type which is a representation of java.math.BigDecimal
267 | */
268 | public static final GraphQLScalarType GraphQLBigDecimal = JavaPrimitives.GraphQLBigDecimal;
269 |
270 | /**
271 | * This represents the "BigInteger" type which is a representation of java.math.BigInteger
272 | */
273 | public static final GraphQLScalarType GraphQLBigInteger = JavaPrimitives.GraphQLBigInteger;
274 |
275 | /**
276 | * This represents the "Char" type which is a representation of java.lang.Character
277 | */
278 | public static final GraphQLScalarType GraphQLChar = JavaPrimitives.GraphQLChar;
279 |
280 | }
281 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/alias/AliasedScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.alias;
2 |
3 | import graphql.Assert;
4 | import graphql.Internal;
5 | import graphql.language.Value;
6 | import graphql.schema.Coercing;
7 | import graphql.schema.CoercingParseLiteralException;
8 | import graphql.schema.CoercingParseValueException;
9 | import graphql.schema.CoercingSerializeException;
10 | import graphql.schema.GraphQLScalarType;
11 |
12 | import java.util.Map;
13 |
14 | /**
15 | * Access this via {@link graphql.scalars.ExtendedScalars#newAliasedScalar(String)}
16 | */
17 | @Internal
18 | public final class AliasedScalar {
19 |
20 | private AliasedScalar() {}
21 |
22 | /**
23 | * A builder for {@link graphql.scalars.alias.AliasedScalar}
24 | */
25 | public static class Builder {
26 | private String name;
27 | private String description;
28 | private GraphQLScalarType aliasedScalar;
29 |
30 | /**
31 | * Sets the name of the aliased scalar
32 | *
33 | * @param name the name of the aliased scalar
34 | *
35 | * @return this builder
36 | */
37 | public Builder name(String name) {
38 | this.name = name;
39 | return this;
40 | }
41 |
42 | /**
43 | * Sets the description of the aliased scalar
44 | *
45 | * @param description the description of the aliased scalar
46 | *
47 | * @return this builder
48 | */
49 | public Builder description(String description) {
50 | this.description = description;
51 | return this;
52 | }
53 |
54 | /**
55 | * Sets the scalar that is to be aliased
56 | *
57 | * @param aliasedScalar the scalar that is to be aliased
58 | *
59 | * @return this builder
60 | */
61 | public Builder aliasedScalar(GraphQLScalarType aliasedScalar) {
62 | this.aliasedScalar = aliasedScalar;
63 | return this;
64 | }
65 |
66 | /**
67 | * @return the built {@link AliasedScalar}
68 | */
69 | public GraphQLScalarType build() {
70 | Assert.assertNotNull(name);
71 | return aliasedScalarImpl(name, description, aliasedScalar);
72 | }
73 | }
74 |
75 |
76 | private static GraphQLScalarType aliasedScalarImpl(String name, String description, GraphQLScalarType aliasedScalar) {
77 | Assert.assertNotNull(aliasedScalar);
78 | Coercing coercing = new Coercing() {
79 | @Override
80 | public Object serialize(Object input) throws CoercingSerializeException {
81 | return aliasedScalar.getCoercing().serialize(input);
82 | }
83 |
84 | @Override
85 | public Object parseValue(Object input) throws CoercingParseValueException {
86 | return aliasedScalar.getCoercing().parseValue(input);
87 | }
88 |
89 | @Override
90 | public Object parseLiteral(Object input) throws CoercingParseLiteralException {
91 | return aliasedScalar.getCoercing().parseLiteral(input);
92 | }
93 |
94 | @Override
95 | public Object parseLiteral(Object input, Map variables) throws CoercingParseLiteralException {
96 | Coercing, ?> c = aliasedScalar.getCoercing();
97 | return c.parseLiteral(input, variables);
98 | }
99 |
100 | @Override
101 | public Value> valueToLiteral(Object input) {
102 | return aliasedScalar.getCoercing().valueToLiteral(input);
103 | }
104 | };
105 | return GraphQLScalarType.newScalar()
106 | .name(name)
107 | .description(description)
108 | .coercing(coercing)
109 | .build();
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/country/code/CountryCode.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.country.code;
2 |
3 | /**
4 | * The CountryCode list as defined by ISO 3166-1 alpha-2.
5 | * See the ISO 3166-1 alpha-2 for more details.
6 | */
7 | public enum CountryCode {
8 | AD, AE, AF, AG, AI, AL, AM, AO, AQ, AR, AS, AT, AU, AW, AX, AZ, BA, BB, BD, BE, BF, BG, BH, BI, BJ, BL, BM, BN, BO,
9 | BQ, BR, BS, BT, BV, BW, BY, BZ, CA, CC, CD, CF, CG, CH, CI, CK, CL, CM, CN, CO, CR, CU, CV, CW, CX, CY, CZ, DE, DJ,
10 | DK, DM, DO, DZ, EC, EE, EG, EH, ER, ES, ET, FI, FJ, FK, FM, FO, FR, GA, GB, GD, GE, GF, GG, GH, GI, GL, GM, GN, GP,
11 | GQ, GR, GS, GT, GU, GW, GY, HK, HM, HN, HR, HT, HU, ID, IE, IL, IM, IN, IO, IQ, IR, IS, IT, JE, JM, JO, JP, KE, KG,
12 | KH, KI, KM, KN, KP, KR, KW, KY, KZ, LA, LB, LC, LI, LK, LR, LS, LT, LU, LV, LY, MA, MC, MD, ME, MF, MG, MH, MK, ML,
13 | MM, MN, MO, MP, MQ, MR, MS, MT, MU, MV, MW, MX, MY, MZ, NA, NC, NE, NF, NG, NI, NL, NO, NP, NR, NU, NZ, OM, PA, PE,
14 | PF, PG, PH, PK, PL, PM, PN, PR, PS, PT, PW, PY, QA, RE, RO, RS, RU, RW, SA, SB, SC, SD, SE, SG, SH, SI, SJ, SK, SL,
15 | SM, SN, SO, SR, SS, ST, SV, SX, SY, SZ, TC, TD, TF, TG, TH, TJ, TK, TL, TM, TN, TO, TR, TT, TV, TW, TZ, UA, UG, UM,
16 | US, UY, UZ, VA, VC, VE, VG, VI, VN, VU, WF, WS, YE, YT, ZA, ZM, ZW
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/country/code/CountryCodeScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.country.code;
2 |
3 | import graphql.Internal;
4 | import graphql.language.StringValue;
5 | import graphql.language.Value;
6 | import graphql.schema.*;
7 |
8 | import java.util.function.Function;
9 |
10 | import static graphql.scalars.util.Kit.typeName;
11 |
12 | /**
13 | * Access this via {@link graphql.scalars.ExtendedScalars#CountryCode}
14 | */
15 | @Internal
16 | public class CountryCodeScalar {
17 |
18 | public static final GraphQLScalarType INSTANCE;
19 |
20 | static {
21 | Coercing coercing = new Coercing() {
22 |
23 | @Override
24 | public String serialize(Object input) throws CoercingSerializeException {
25 | CountryCode countryCode = parseCountryCode(input, CoercingParseValueException::new);
26 | return countryCode.name();
27 | }
28 |
29 | @Override
30 | public CountryCode parseValue(Object input) throws CoercingParseValueException {
31 | return parseCountryCode(input, CoercingParseValueException::new);
32 | }
33 |
34 | @Override
35 | public CountryCode parseLiteral(Object input) throws CoercingParseLiteralException {
36 | if (!(input instanceof StringValue)) {
37 | throw new CoercingParseLiteralException("Expected AST type 'StringValue' but was '" + typeName(input) + "'.");
38 | }
39 | String stringValue = ((StringValue) input).getValue();
40 | return parseCountryCode(stringValue, CoercingParseLiteralException::new);
41 |
42 | }
43 |
44 | @Override
45 | public Value> valueToLiteral(Object input) {
46 | String s = serialize(input);
47 | return StringValue.newStringValue(s).build();
48 | }
49 |
50 | private CountryCode parseCountryCode(Object input, Function exceptionMaker) {
51 | final CountryCode result;
52 | if (input instanceof String) {
53 | try {
54 | result = CountryCode.valueOf((String) input);
55 | } catch (NullPointerException | IllegalArgumentException ex) {
56 | throw exceptionMaker.apply("Invalid ISO 3166-1 alpha-2 value : '" + input + "'. because of : '" + ex.getMessage() + "'");
57 | }
58 | } else if (input instanceof CountryCode) {
59 | result = (CountryCode) input;
60 | } else {
61 | throw exceptionMaker.apply("Expected a 'String' or 'CountryCode' but was '" + typeName(input) + "'.");
62 | }
63 | return result;
64 | }
65 | };
66 |
67 | INSTANCE = GraphQLScalarType.newScalar()
68 | .name("CountryCode")
69 | .description("The CountryCode scalar type as defined by ISO 3166-1 alpha-2.")
70 | .coercing(coercing).build();
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/currency/CurrencyScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.currency;
2 |
3 | import graphql.Internal;
4 | import graphql.language.StringValue;
5 | import graphql.language.Value;
6 | import graphql.schema.*;
7 |
8 | import java.util.Currency;
9 | import java.util.function.Function;
10 |
11 | import static graphql.scalars.util.Kit.typeName;
12 |
13 | /**
14 | * Access this via {@link graphql.scalars.ExtendedScalars#Currency}
15 | */
16 | @Internal
17 | public class CurrencyScalar {
18 |
19 | public static final GraphQLScalarType INSTANCE;
20 |
21 | static {
22 | Coercing coercing = new Coercing() {
23 | @Override
24 | public String serialize(Object input) throws CoercingSerializeException {
25 | Currency currency = parseCurrency(input, CoercingSerializeException::new);
26 | return currency.getCurrencyCode();
27 | }
28 |
29 | @Override
30 | public Currency parseValue(Object input) throws CoercingParseValueException {
31 | return parseCurrency(input, CoercingParseValueException::new);
32 | }
33 |
34 |
35 | @Override
36 | public Currency parseLiteral(Object input) throws CoercingParseLiteralException {
37 | if (!(input instanceof StringValue)) {
38 | throw new CoercingParseLiteralException("Expected AST type 'StringValue' but was '" + typeName(input) + "'.");
39 | }
40 | String stringValue = ((StringValue) input).getValue();
41 | return parseCurrency(stringValue, CoercingParseLiteralException::new);
42 | }
43 |
44 | @Override
45 | public Value> valueToLiteral(Object input) {
46 | String serializedInput = serialize(input);
47 | return StringValue.newStringValue(serializedInput).build();
48 | }
49 |
50 |
51 | private Currency parseCurrency(Object input, Function exceptionMaker) {
52 | final Currency result;
53 | if (input instanceof Currency) {
54 | result = (Currency) input;
55 | } else if (input instanceof String) {
56 | try {
57 | result = Currency.getInstance((String) input);
58 | } catch (NullPointerException | IllegalArgumentException ex) {
59 | throw exceptionMaker.apply("Invalid ISO 4217 value : '" + input + "'. because of : '" + ex.getMessage() + "'");
60 | }
61 | } else {
62 | throw exceptionMaker.apply("Expected a 'String' or 'Currency' but was '" + typeName(input) + "'.");
63 | }
64 | return result;
65 | }
66 | };
67 |
68 | INSTANCE = GraphQLScalarType.newScalar()
69 | .name("Currency")
70 | .description("An ISO-4217 compliant Currency Scalar")
71 | .coercing(coercing).build();
72 | }
73 | }
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/datetime/DateScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.datetime;
2 |
3 | import graphql.Internal;
4 | import graphql.language.StringValue;
5 | import graphql.language.Value;
6 | import graphql.schema.Coercing;
7 | import graphql.schema.CoercingParseLiteralException;
8 | import graphql.schema.CoercingParseValueException;
9 | import graphql.schema.CoercingSerializeException;
10 | import graphql.schema.GraphQLScalarType;
11 |
12 | import java.time.DateTimeException;
13 | import java.time.LocalDate;
14 | import java.time.format.DateTimeFormatter;
15 | import java.time.format.DateTimeParseException;
16 | import java.time.temporal.TemporalAccessor;
17 | import java.util.function.Function;
18 |
19 | import static graphql.scalars.util.Kit.typeName;
20 |
21 | /**
22 | * Access this via {@link graphql.scalars.ExtendedScalars#Date}
23 | */
24 | @Internal
25 | public final class DateScalar {
26 |
27 | private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
28 |
29 | public static final GraphQLScalarType INSTANCE;
30 |
31 | private DateScalar() {}
32 |
33 | static {
34 | Coercing coercing = new Coercing() {
35 | @Override
36 | public String serialize(Object input) throws CoercingSerializeException {
37 | TemporalAccessor temporalAccessor;
38 | if (input instanceof TemporalAccessor) {
39 | temporalAccessor = (TemporalAccessor) input;
40 | } else if (input instanceof String) {
41 | temporalAccessor = parseLocalDate(input.toString(), CoercingSerializeException::new);
42 | } else {
43 | throw new CoercingSerializeException(
44 | "Expected a 'String' or 'java.time.temporal.TemporalAccessor' but was '" + typeName(input) + "'."
45 | );
46 | }
47 | try {
48 | return DATE_FORMATTER.format(temporalAccessor);
49 | } catch (DateTimeException e) {
50 | throw new CoercingSerializeException(
51 | "Unable to turn TemporalAccessor into full date because of : '" + e.getMessage() + "'."
52 | );
53 | }
54 | }
55 |
56 | @Override
57 | public LocalDate parseValue(Object input) throws CoercingParseValueException {
58 | TemporalAccessor temporalAccessor;
59 | if (input instanceof TemporalAccessor) {
60 | temporalAccessor = (TemporalAccessor) input;
61 | } else if (input instanceof String) {
62 | temporalAccessor = parseLocalDate(input.toString(), CoercingParseValueException::new);
63 | } else {
64 | throw new CoercingParseValueException(
65 | "Expected a 'String' or 'java.time.temporal.TemporalAccessor' but was '" + typeName(input) + "'."
66 | );
67 | }
68 | try {
69 | return LocalDate.from(temporalAccessor);
70 | } catch (DateTimeException e) {
71 | throw new CoercingParseValueException(
72 | "Unable to turn TemporalAccessor into full date because of : '" + e.getMessage() + "'."
73 | );
74 | }
75 | }
76 |
77 | @Override
78 | public LocalDate parseLiteral(Object input) throws CoercingParseLiteralException {
79 | if (!(input instanceof StringValue)) {
80 | throw new CoercingParseLiteralException(
81 | "Expected AST type 'StringValue' but was '" + typeName(input) + "'."
82 | );
83 | }
84 | return parseLocalDate(((StringValue) input).getValue(), CoercingParseLiteralException::new);
85 | }
86 |
87 | @Override
88 | public Value> valueToLiteral(Object input) {
89 | String s = serialize(input);
90 | return StringValue.newStringValue(s).build();
91 | }
92 |
93 | private LocalDate parseLocalDate(String s, Function exceptionMaker) {
94 | try {
95 | TemporalAccessor temporalAccessor = DATE_FORMATTER.parse(s);
96 | return LocalDate.from(temporalAccessor);
97 | } catch (DateTimeParseException e) {
98 | throw exceptionMaker.apply("Invalid RFC3339 full date value : '" + s + "'. because of : '" + e.getMessage() + "'");
99 | }
100 | }
101 | };
102 |
103 | INSTANCE = GraphQLScalarType.newScalar()
104 | .name("Date")
105 | .description("An RFC-3339 compliant Full Date Scalar")
106 | .coercing(coercing)
107 | .build();
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/datetime/DateTimeScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.datetime;
2 |
3 | import graphql.Internal;
4 | import graphql.language.StringValue;
5 | import graphql.language.Value;
6 | import graphql.schema.Coercing;
7 | import graphql.schema.CoercingParseLiteralException;
8 | import graphql.schema.CoercingParseValueException;
9 | import graphql.schema.CoercingSerializeException;
10 | import graphql.schema.GraphQLScalarType;
11 |
12 | import java.time.DateTimeException;
13 | import java.time.OffsetDateTime;
14 | import java.time.ZonedDateTime;
15 | import java.time.format.DateTimeFormatter;
16 | import java.time.format.DateTimeFormatterBuilder;
17 | import java.time.format.DateTimeParseException;
18 | import java.util.function.Function;
19 |
20 | import static graphql.scalars.util.Kit.typeName;
21 | import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE;
22 | import static java.time.temporal.ChronoField.HOUR_OF_DAY;
23 | import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
24 | import static java.time.temporal.ChronoField.NANO_OF_SECOND;
25 | import static java.time.temporal.ChronoField.OFFSET_SECONDS;
26 | import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
27 |
28 | /**
29 | * Access this via {@link graphql.scalars.ExtendedScalars#DateTime}
30 | */
31 | @Internal
32 | public final class DateTimeScalar {
33 |
34 | public static final GraphQLScalarType INSTANCE;
35 |
36 | private DateTimeScalar() {}
37 | private static final DateTimeFormatter customOutputFormatter = getCustomDateTimeFormatter();
38 |
39 | static {
40 | Coercing coercing = new Coercing() {
41 | @Override
42 | public String serialize(Object input) throws CoercingSerializeException {
43 | OffsetDateTime offsetDateTime;
44 | if (input instanceof OffsetDateTime) {
45 | offsetDateTime = (OffsetDateTime) input;
46 | } else if (input instanceof ZonedDateTime) {
47 | offsetDateTime = ((ZonedDateTime) input).toOffsetDateTime();
48 | } else if (input instanceof String) {
49 | offsetDateTime = parseOffsetDateTime(input.toString(), CoercingSerializeException::new);
50 | } else {
51 | throw new CoercingSerializeException(
52 | "Expected something we can convert to 'java.time.OffsetDateTime' but was '" + typeName(input) + "'."
53 | );
54 | }
55 | try {
56 | return customOutputFormatter.format(offsetDateTime);
57 | } catch (DateTimeException e) {
58 | throw new CoercingSerializeException(
59 | "Unable to turn TemporalAccessor into OffsetDateTime because of : '" + e.getMessage() + "'."
60 | );
61 | }
62 | }
63 |
64 | @Override
65 | public OffsetDateTime parseValue(Object input) throws CoercingParseValueException {
66 | OffsetDateTime offsetDateTime;
67 | if (input instanceof OffsetDateTime) {
68 | offsetDateTime = (OffsetDateTime) input;
69 | } else if (input instanceof ZonedDateTime) {
70 | offsetDateTime = ((ZonedDateTime) input).toOffsetDateTime();
71 | } else if (input instanceof String) {
72 | offsetDateTime = parseOffsetDateTime(input.toString(), CoercingParseValueException::new);
73 | } else {
74 | throw new CoercingParseValueException(
75 | "Expected a 'String' but was '" + typeName(input) + "'."
76 | );
77 | }
78 | return offsetDateTime;
79 | }
80 |
81 | @Override
82 | public OffsetDateTime parseLiteral(Object input) throws CoercingParseLiteralException {
83 | if (!(input instanceof StringValue)) {
84 | throw new CoercingParseLiteralException(
85 | "Expected AST type 'StringValue' but was '" + typeName(input) + "'."
86 | );
87 | }
88 | return parseOffsetDateTime(((StringValue) input).getValue(), CoercingParseLiteralException::new);
89 | }
90 |
91 | @Override
92 | public Value> valueToLiteral(Object input) {
93 | String s = serialize(input);
94 | return StringValue.newStringValue(s).build();
95 | }
96 |
97 | private OffsetDateTime parseOffsetDateTime(String s, Function exceptionMaker) {
98 | try {
99 | OffsetDateTime parse = OffsetDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
100 | if (parse.get(OFFSET_SECONDS) == 0 && s.endsWith("-00:00")) {
101 | throw exceptionMaker.apply("Invalid value : '" + s + "'. Negative zero offset is not allowed");
102 | }
103 | return parse;
104 | } catch (DateTimeParseException e) {
105 | throw exceptionMaker.apply("Invalid RFC3339 value : '" + s + "'. because of : '" + e.getMessage() + "'");
106 | }
107 | }
108 | };
109 |
110 | INSTANCE = GraphQLScalarType.newScalar()
111 | .name("DateTime")
112 | .description("A slightly refined version of RFC-3339 compliant DateTime Scalar")
113 | .specifiedByUrl("https://scalars.graphql.org/andimarek/date-time") // TODO: Change to .specifiedByURL when builder added to graphql-java
114 | .coercing(coercing)
115 | .build();
116 | }
117 |
118 | private static DateTimeFormatter getCustomDateTimeFormatter() {
119 | return new DateTimeFormatterBuilder()
120 | .parseCaseInsensitive()
121 | .append(ISO_LOCAL_DATE)
122 | .appendLiteral('T')
123 | .appendValue(HOUR_OF_DAY, 2)
124 | .appendLiteral(':')
125 | .appendValue(MINUTE_OF_HOUR, 2)
126 | .appendLiteral(':')
127 | .appendValue(SECOND_OF_MINUTE, 2)
128 | .appendFraction(NANO_OF_SECOND, 3, 3, true)
129 | .appendOffset("+HH:MM", "Z")
130 | .toFormatter();
131 | }
132 |
133 | }
134 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/datetime/LocalTimeCoercing.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.datetime;
2 |
3 | import graphql.language.StringValue;
4 | import graphql.schema.Coercing;
5 | import graphql.schema.CoercingParseLiteralException;
6 | import graphql.schema.CoercingParseValueException;
7 | import graphql.schema.CoercingSerializeException;
8 |
9 | import java.time.DateTimeException;
10 | import java.time.LocalTime;
11 | import java.time.format.DateTimeFormatter;
12 | import java.time.format.DateTimeParseException;
13 | import java.time.temporal.TemporalAccessor;
14 | import java.util.function.Function;
15 |
16 | import static graphql.scalars.util.Kit.typeName;
17 |
18 | public class LocalTimeCoercing implements Coercing {
19 |
20 | private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ISO_LOCAL_TIME;
21 |
22 | @Override
23 | public String serialize(final Object input) throws CoercingSerializeException {
24 | TemporalAccessor temporalAccessor;
25 | if (input instanceof TemporalAccessor) {
26 | temporalAccessor = (TemporalAccessor) input;
27 | } else if (input instanceof String) {
28 | temporalAccessor = parseTime(input.toString(), CoercingSerializeException::new);
29 | } else {
30 | throw new CoercingSerializeException(
31 | "Expected a 'String' or 'java.time.temporal.TemporalAccessor' but was '" + typeName(input) + "'."
32 | );
33 | }
34 | try {
35 | return DATE_FORMATTER.format(temporalAccessor);
36 | } catch (DateTimeException e) {
37 | throw new CoercingSerializeException(
38 | "Unable to turn TemporalAccessor into full time because of : '" + e.getMessage() + "'."
39 | );
40 | }
41 | }
42 |
43 | @Override
44 | public LocalTime parseValue(final Object input) throws CoercingParseValueException {
45 | TemporalAccessor temporalAccessor;
46 | if (input instanceof TemporalAccessor) {
47 | temporalAccessor = (TemporalAccessor) input;
48 | } else if (input instanceof String) {
49 | temporalAccessor = parseTime(input.toString(), CoercingParseValueException::new);
50 | } else {
51 | throw new CoercingParseValueException(
52 | "Expected a 'String' or 'java.time.temporal.TemporalAccessor' but was '" + typeName(input) + "'."
53 | );
54 | }
55 | try {
56 | return LocalTime.from(temporalAccessor);
57 | } catch (DateTimeException e) {
58 | throw new CoercingParseValueException(
59 | "Unable to turn TemporalAccessor into full time because of : '" + e.getMessage() + "'."
60 | );
61 | }
62 | }
63 |
64 | @Override
65 | public LocalTime parseLiteral(final Object input) throws CoercingParseLiteralException {
66 | if (!(input instanceof StringValue)) {
67 | throw new CoercingParseLiteralException(
68 | "Expected AST type 'StringValue' but was '" + typeName(input) + "'."
69 | );
70 | }
71 | return parseTime(((StringValue) input).getValue(), CoercingParseLiteralException::new);
72 | }
73 |
74 | private static LocalTime parseTime(String s, Function exceptionMaker) {
75 | try {
76 | TemporalAccessor temporalAccessor = DATE_FORMATTER.parse(s);
77 | return LocalTime.from(temporalAccessor);
78 | } catch (DateTimeParseException e) {
79 | throw exceptionMaker.apply("Invalid local time value : '" + s + "'. because of : '" + e.getMessage() + "'");
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/datetime/TimeScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.datetime;
2 |
3 | import graphql.Internal;
4 | import graphql.language.StringValue;
5 | import graphql.language.Value;
6 | import graphql.schema.Coercing;
7 | import graphql.schema.CoercingParseLiteralException;
8 | import graphql.schema.CoercingParseValueException;
9 | import graphql.schema.CoercingSerializeException;
10 | import graphql.schema.GraphQLScalarType;
11 |
12 | import java.time.DateTimeException;
13 | import java.time.OffsetTime;
14 | import java.time.format.DateTimeFormatter;
15 | import java.time.format.DateTimeParseException;
16 | import java.time.temporal.TemporalAccessor;
17 | import java.util.function.Function;
18 |
19 | import static graphql.scalars.util.Kit.typeName;
20 |
21 | /**
22 | * Access this via {@link graphql.scalars.ExtendedScalars#Time}
23 | */
24 | @Internal
25 | public final class TimeScalar {
26 |
27 | private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ISO_OFFSET_TIME;
28 |
29 | public static final GraphQLScalarType INSTANCE;
30 |
31 | private TimeScalar() {}
32 |
33 | static {
34 | Coercing coercing = new Coercing() {
35 | @Override
36 | public String serialize(Object input) throws CoercingSerializeException {
37 | TemporalAccessor temporalAccessor;
38 | if (input instanceof TemporalAccessor) {
39 | temporalAccessor = (TemporalAccessor) input;
40 | } else if (input instanceof String) {
41 | temporalAccessor = parseOffsetTime(input.toString(), CoercingSerializeException::new);
42 | } else {
43 | throw new CoercingSerializeException(
44 | "Expected a 'String' or 'java.time.temporal.TemporalAccessor' but was '" + typeName(input) + "'."
45 | );
46 | }
47 | try {
48 | return dateFormatter.format(temporalAccessor);
49 | } catch (DateTimeException e) {
50 | throw new CoercingSerializeException(
51 | "Unable to turn TemporalAccessor into full time because of : '" + e.getMessage() + "'."
52 | );
53 | }
54 | }
55 |
56 | @Override
57 | public OffsetTime parseValue(Object input) throws CoercingParseValueException {
58 | TemporalAccessor temporalAccessor;
59 | if (input instanceof TemporalAccessor) {
60 | temporalAccessor = (TemporalAccessor) input;
61 | } else if (input instanceof String) {
62 | temporalAccessor = parseOffsetTime(input.toString(), CoercingParseValueException::new);
63 | } else {
64 | throw new CoercingParseValueException(
65 | "Expected a 'String' or 'java.time.temporal.TemporalAccessor' but was '" + typeName(input) + "'."
66 | );
67 | }
68 | try {
69 | return OffsetTime.from(temporalAccessor);
70 | } catch (DateTimeException e) {
71 | throw new CoercingParseValueException(
72 | "Unable to turn TemporalAccessor into full time because of : '" + e.getMessage() + "'."
73 | );
74 | }
75 | }
76 |
77 | @Override
78 | public OffsetTime parseLiteral(Object input) throws CoercingParseLiteralException {
79 | if (!(input instanceof StringValue)) {
80 | throw new CoercingParseLiteralException(
81 | "Expected AST type 'StringValue' but was '" + typeName(input) + "'."
82 | );
83 | }
84 | return parseOffsetTime(((StringValue) input).getValue(), CoercingParseLiteralException::new);
85 | }
86 |
87 | @Override
88 | public Value> valueToLiteral(Object input) {
89 | String s = serialize(input);
90 | return StringValue.newStringValue(s).build();
91 | }
92 |
93 | private OffsetTime parseOffsetTime(String s, Function exceptionMaker) {
94 | try {
95 | TemporalAccessor temporalAccessor = dateFormatter.parse(s);
96 | return OffsetTime.from(temporalAccessor);
97 | } catch (DateTimeParseException e) {
98 | throw exceptionMaker.apply("Invalid RFC3339 full time value : '" + s + "'. because of : '" + e.getMessage() + "'");
99 | }
100 | }
101 | };
102 |
103 | INSTANCE = GraphQLScalarType.newScalar()
104 | .name("Time")
105 | .description("An RFC-3339 compliant Full Time Scalar")
106 | .coercing(coercing)
107 | .build();
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/id/UUIDScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.id;
2 |
3 | import graphql.Internal;
4 | import graphql.language.StringValue;
5 | import graphql.language.Value;
6 | import graphql.scalars.util.Kit;
7 | import graphql.schema.Coercing;
8 | import graphql.schema.CoercingParseLiteralException;
9 | import graphql.schema.CoercingParseValueException;
10 | import graphql.schema.CoercingSerializeException;
11 | import graphql.schema.GraphQLScalarType;
12 |
13 | import java.util.UUID;
14 |
15 | import static graphql.scalars.util.Kit.typeName;
16 |
17 | /**
18 | * Access this via {@link graphql.scalars.ExtendedScalars#UUID}
19 | */
20 | @Internal
21 | public class UUIDScalar {
22 |
23 | public static GraphQLScalarType INSTANCE;
24 |
25 | static {
26 | Coercing coercing = new Coercing() {
27 | private UUID convertImpl(Object input) {
28 | if (input instanceof String) {
29 | try {
30 | return (UUID.fromString((String) input));
31 | } catch (IllegalArgumentException ex) {
32 | return null;
33 | }
34 | } else if (input instanceof UUID) {
35 | return (UUID) input;
36 | }
37 | return null;
38 | }
39 |
40 | @Override
41 | public String serialize(Object input) throws CoercingSerializeException {
42 | UUID result = convertImpl(input);
43 | if (result == null) {
44 | throw new CoercingSerializeException(
45 | "Expected type 'UUID' but was '" + Kit.typeName(input) + "'."
46 | );
47 | }
48 | return result.toString();
49 | }
50 |
51 | @Override
52 | public UUID parseValue(Object input) throws CoercingParseValueException {
53 | UUID result = convertImpl(input);
54 | if (result == null) {
55 | throw new CoercingParseValueException(
56 | "Expected type 'UUID' but was '" + Kit.typeName(input) + "'."
57 | );
58 | }
59 | return result;
60 | }
61 |
62 | @Override
63 | public UUID parseLiteral(Object input) throws CoercingParseLiteralException {
64 | if (!(input instanceof StringValue)) {
65 | throw new CoercingParseLiteralException(
66 | "Expected a 'java.util.UUID' AST type object but was '" + typeName(input) + "'."
67 | );
68 | }
69 | try {
70 | return UUID.fromString(((StringValue) input).getValue());
71 | } catch (IllegalArgumentException ex) {
72 | throw new CoercingParseLiteralException(
73 | "Expected something that we can convert to a UUID but was invalid"
74 | );
75 | }
76 | }
77 |
78 | @Override
79 | public Value> valueToLiteral(Object input) {
80 | String s = serialize(input);
81 | return StringValue.newStringValue(s).build();
82 | }
83 | };
84 |
85 |
86 | INSTANCE = GraphQLScalarType.newScalar()
87 | .name("UUID")
88 | .description("A universally unique identifier compliant UUID Scalar")
89 | .coercing(coercing)
90 | .build();
91 |
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/locale/LocaleScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.locale;
2 |
3 | import graphql.Internal;
4 | import graphql.language.StringValue;
5 | import graphql.language.Value;
6 | import graphql.schema.Coercing;
7 | import graphql.schema.CoercingParseLiteralException;
8 | import graphql.schema.CoercingParseValueException;
9 | import graphql.schema.CoercingSerializeException;
10 | import graphql.schema.GraphQLScalarType;
11 |
12 | import java.util.Locale;
13 |
14 | import static graphql.scalars.util.Kit.typeName;
15 |
16 | /**
17 | * Access this via {@link graphql.scalars.ExtendedScalars#Locale}
18 | */
19 | @Internal
20 | public final class LocaleScalar {
21 |
22 | private LocaleScalar() {}
23 |
24 | public static final GraphQLScalarType INSTANCE;
25 |
26 | static {
27 | Coercing coercing = new Coercing() {
28 |
29 | @Override
30 | public String serialize(Object input) throws CoercingSerializeException {
31 | if (input instanceof String) {
32 | try {
33 | return Locale.forLanguageTag((String) input).toLanguageTag();
34 | } catch (Exception e) {
35 | throw new CoercingSerializeException(
36 | "Expected a valid language tag string but was but was " + typeName(input));
37 | }
38 | }
39 | if (input instanceof Locale) {
40 | return ((Locale) input).toLanguageTag();
41 | } else {
42 | throw new CoercingSerializeException(
43 | "Expected a 'java.util.Locale' object but was " + typeName(input));
44 | }
45 | }
46 |
47 | @Override
48 | public Locale parseValue(Object input) throws CoercingParseValueException {
49 | if (input instanceof String) {
50 | try {
51 | return Locale.forLanguageTag(input.toString());
52 | } catch (Exception e) {
53 | throw new CoercingParseValueException(
54 | "Unable to parse value to 'java.util.Locale' because of: " + e.getMessage());
55 | }
56 | } else if (input instanceof Locale) {
57 | return (Locale) input;
58 | } else {
59 | throw new CoercingParseValueException(
60 | "Expected a 'java.lang.String' object but was " + typeName(input));
61 | }
62 | }
63 |
64 | @Override
65 | public Locale parseLiteral(Object input) throws CoercingParseLiteralException {
66 | if (input instanceof StringValue) {
67 | return Locale.forLanguageTag(((StringValue) input).getValue());
68 | } else {
69 | throw new CoercingParseLiteralException(
70 | "Expected a 'java.lang.String' object but was " + typeName(input));
71 | }
72 | }
73 |
74 | @Override
75 | public Value> valueToLiteral(Object input) {
76 | String s = serialize(input);
77 | return StringValue.newStringValue(s).build();
78 | }
79 | };
80 |
81 | INSTANCE = GraphQLScalarType.newScalar()
82 | .name("Locale")
83 | .description("A IETF BCP 47 language tag")
84 | .coercing(coercing)
85 | .build();
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/numeric/FloatCoercing.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric;
2 |
3 | import graphql.Internal;
4 | import graphql.language.Value;
5 | import graphql.schema.Coercing;
6 | import graphql.schema.CoercingParseLiteralException;
7 | import graphql.schema.CoercingParseValueException;
8 | import graphql.schema.CoercingSerializeException;
9 |
10 | import java.util.function.Function;
11 |
12 | import static graphql.Scalars.GraphQLFloat;
13 |
14 | @Internal
15 | abstract class FloatCoercing implements Coercing {
16 |
17 | protected abstract Double check(Double d, Function exceptionMaker);
18 |
19 | @Override
20 | public Double serialize(Object input) throws CoercingSerializeException {
21 | Double d = (Double) GraphQLFloat.getCoercing().serialize(input);
22 | return check(d, CoercingSerializeException::new);
23 | }
24 |
25 | @Override
26 | public Double parseValue(Object input) throws CoercingParseValueException {
27 | Double d = (Double) GraphQLFloat.getCoercing().parseValue(input);
28 | return check(d, CoercingParseValueException::new);
29 | }
30 |
31 | @Override
32 | public Double parseLiteral(Object input) throws CoercingParseLiteralException {
33 | Double d = (Double) GraphQLFloat.getCoercing().parseLiteral(input);
34 | return check(d, CoercingParseLiteralException::new);
35 | }
36 |
37 | @Override
38 | public Value> valueToLiteral(Object input) {
39 | return GraphQLFloat.getCoercing().valueToLiteral(input);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/numeric/IntCoercing.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric;
2 |
3 | import graphql.Internal;
4 | import graphql.language.Value;
5 | import graphql.schema.Coercing;
6 | import graphql.schema.CoercingParseLiteralException;
7 | import graphql.schema.CoercingParseValueException;
8 | import graphql.schema.CoercingSerializeException;
9 |
10 | import java.util.function.Function;
11 |
12 | import static graphql.Scalars.GraphQLInt;
13 |
14 | @Internal
15 | abstract class IntCoercing implements Coercing {
16 |
17 | protected abstract Integer check(Integer i, Function exceptionMaker);
18 |
19 | @Override
20 | public Integer serialize(Object input) throws CoercingSerializeException {
21 | Integer i = (Integer) GraphQLInt.getCoercing().serialize(input);
22 | return check(i, CoercingSerializeException::new);
23 | }
24 |
25 | @Override
26 | public Integer parseValue(Object input) throws CoercingParseValueException {
27 | Integer i = (Integer) GraphQLInt.getCoercing().parseValue(input);
28 | return check(i, CoercingParseValueException::new);
29 | }
30 |
31 | @Override
32 | public Integer parseLiteral(Object input) throws CoercingParseLiteralException {
33 | Integer i = (Integer) GraphQLInt.getCoercing().parseLiteral(input);
34 | return check(i, CoercingParseLiteralException::new);
35 | }
36 |
37 | @Override
38 | public Value> valueToLiteral(Object input) {
39 | return GraphQLInt.getCoercing().valueToLiteral(input);
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/numeric/NegativeFloatScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric;
2 |
3 | import graphql.Internal;
4 | import graphql.schema.GraphQLScalarType;
5 |
6 | import java.util.function.Function;
7 |
8 | /**
9 | * Access this via {@link graphql.scalars.ExtendedScalars#NegativeFloat}
10 | */
11 | @Internal
12 | public final class NegativeFloatScalar {
13 |
14 | private NegativeFloatScalar() {}
15 |
16 | public static final GraphQLScalarType INSTANCE = GraphQLScalarType.newScalar()
17 | .name("NegativeFloat")
18 | .description("An Float scalar that must be a negative value")
19 | .coercing(new FloatCoercing() {
20 | @Override
21 | protected Double check(Double d, Function exceptionMaker) {
22 | if (d >= 0.0d) {
23 | throw exceptionMaker.apply("The value must be a negative value");
24 | }
25 | return d;
26 | }
27 | })
28 | .build();
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/numeric/NegativeIntScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric;
2 |
3 | import graphql.Internal;
4 | import graphql.schema.GraphQLScalarType;
5 |
6 | import java.util.function.Function;
7 |
8 | /**
9 | * Access this via {@link graphql.scalars.ExtendedScalars#NegativeInt}
10 | */
11 | @Internal
12 | public final class NegativeIntScalar {
13 |
14 | private NegativeIntScalar() {}
15 |
16 | public static final GraphQLScalarType INSTANCE = GraphQLScalarType.newScalar()
17 | .name("NegativeInt")
18 | .description("An Int scalar that must be a negative value")
19 | .coercing(new IntCoercing() {
20 | @Override
21 | protected Integer check(Integer i, Function exceptionMaker) {
22 | if (i >= 0) {
23 | throw exceptionMaker.apply("The value must be a negative integer");
24 | }
25 | return i;
26 | }
27 | })
28 | .build();
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/numeric/NonNegativeFloatScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric;
2 |
3 | import graphql.Internal;
4 | import graphql.schema.GraphQLScalarType;
5 |
6 | import java.util.function.Function;
7 |
8 | /**
9 | * Access this via {@link graphql.scalars.ExtendedScalars#NonNegativeFloat}
10 | */
11 | @Internal
12 | public final class NonNegativeFloatScalar {
13 |
14 | private NonNegativeFloatScalar() {}
15 |
16 | public static final GraphQLScalarType INSTANCE = GraphQLScalarType.newScalar()
17 | .name("NonNegativeFloat")
18 | .description("An Float scalar that must be greater than or equal to zero")
19 | .coercing(new FloatCoercing() {
20 | @Override
21 | protected Double check(Double d, Function exceptionMaker) {
22 | if (d < 0.0d) {
23 | throw exceptionMaker.apply("The value must be greater than or equal to zero");
24 | }
25 | return d;
26 | }
27 | })
28 | .build();
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/numeric/NonNegativeIntScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric;
2 |
3 | import graphql.Internal;
4 | import graphql.schema.GraphQLScalarType;
5 |
6 | import java.util.function.Function;
7 |
8 | /**
9 | * Access this via {@link graphql.scalars.ExtendedScalars#NonNegativeInt}
10 | */
11 | @Internal
12 | public final class NonNegativeIntScalar {
13 |
14 | private NonNegativeIntScalar() {}
15 |
16 | public static final GraphQLScalarType INSTANCE = GraphQLScalarType.newScalar()
17 | .name("NonNegativeInt")
18 | .description("An Int scalar that must be greater than or equal to zero")
19 | .coercing(new IntCoercing() {
20 | @Override
21 | protected Integer check(Integer i, Function exceptionMaker) {
22 | if (i < 0) {
23 | throw exceptionMaker.apply("The value must be greater than or equal to zero");
24 | }
25 | return i;
26 | }
27 | })
28 | .build();
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/numeric/NonPositiveFloatScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric;
2 |
3 | import graphql.Internal;
4 | import graphql.schema.GraphQLScalarType;
5 |
6 | import java.util.function.Function;
7 |
8 | /**
9 | * Access this via {@link graphql.scalars.ExtendedScalars#NonPositiveFloat}
10 | */
11 | @Internal
12 | public final class NonPositiveFloatScalar {
13 |
14 | private NonPositiveFloatScalar() {}
15 |
16 | public static final GraphQLScalarType INSTANCE = GraphQLScalarType.newScalar()
17 | .name("NonPositiveFloat").description("An Float scalar that must be less than or equal to zero")
18 | .coercing(new FloatCoercing() {
19 | @Override
20 | protected Double check(Double d, Function exceptionMaker) {
21 | if (d > 0) {
22 | throw exceptionMaker.apply("The value must be less than or equal to zero");
23 | }
24 | return d;
25 | }
26 | })
27 | .build();
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/numeric/NonPositiveIntScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric;
2 |
3 | import graphql.Internal;
4 | import graphql.schema.GraphQLScalarType;
5 |
6 | import java.util.function.Function;
7 |
8 | /**
9 | * Access this via {@link graphql.scalars.ExtendedScalars#NonPositiveInt}
10 | */
11 | @Internal
12 | public final class NonPositiveIntScalar {
13 |
14 | private NonPositiveIntScalar() {}
15 |
16 | public static final GraphQLScalarType INSTANCE = GraphQLScalarType.newScalar()
17 | .name("NonPositiveInt")
18 | .description("An Int scalar that must be less than or equal to zero")
19 | .coercing(new IntCoercing() {
20 | @Override
21 | protected Integer check(Integer i, Function exceptionMaker) {
22 | if (i > 0) {
23 | throw exceptionMaker.apply("The value must be less than or equal to zero");
24 | }
25 | return i;
26 | }
27 | })
28 | .build();
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/numeric/PositiveFloatScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric;
2 |
3 | import graphql.Internal;
4 | import graphql.schema.GraphQLScalarType;
5 |
6 | import java.util.function.Function;
7 |
8 | /**
9 | * Access this via {@link graphql.scalars.ExtendedScalars#PositiveFloat}
10 | */
11 | @Internal
12 | public final class PositiveFloatScalar {
13 |
14 | private PositiveFloatScalar() {}
15 |
16 | public static final GraphQLScalarType INSTANCE = GraphQLScalarType.newScalar()
17 | .name("PositiveFloat")
18 | .description("An Float scalar that must be a positive value")
19 | .coercing(new FloatCoercing() {
20 | @Override
21 | protected Double check(Double d, Function exceptionMaker) {
22 | if (d <= 0) {
23 | throw exceptionMaker.apply("The value must be a positive value");
24 | }
25 | return d;
26 | }
27 | })
28 | .build();
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/numeric/PositiveIntScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric;
2 |
3 | import graphql.Internal;
4 | import graphql.schema.GraphQLScalarType;
5 |
6 | import java.util.function.Function;
7 |
8 | /**
9 | * Access this via {@link graphql.scalars.ExtendedScalars#PositiveInt}
10 | */
11 | @Internal
12 | public final class PositiveIntScalar {
13 |
14 | private PositiveIntScalar() {}
15 |
16 | public static final GraphQLScalarType INSTANCE = GraphQLScalarType.newScalar()
17 | .name("PositiveInt")
18 | .description("An Int scalar that must be a positive value")
19 | .coercing(new IntCoercing() {
20 | @Override
21 | protected Integer check(Integer i, Function exceptionMaker) {
22 | if (i <= 0) {
23 | throw exceptionMaker.apply("The value must be a positive integer");
24 | }
25 | return i;
26 | }
27 | })
28 | .build();
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/object/JsonScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.object;
2 |
3 | import graphql.Internal;
4 | import graphql.schema.GraphQLScalarType;
5 |
6 | import static graphql.scalars.object.ObjectScalar.OBJECT_COERCING;
7 |
8 | /**
9 | * A synonym class for {@link graphql.scalars.object.ObjectScalar}
10 | *
11 | * Access this via {@link graphql.scalars.ExtendedScalars#Json}
12 | */
13 | @Internal
14 | public final class JsonScalar {
15 |
16 | private JsonScalar() {}
17 |
18 | public static final GraphQLScalarType INSTANCE = GraphQLScalarType.newScalar()
19 | .name("JSON")
20 | .description("A JSON scalar")
21 | .coercing(OBJECT_COERCING)
22 | .build();
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/object/ObjectScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.object;
2 |
3 | import graphql.Assert;
4 | import graphql.Internal;
5 | import graphql.language.ArrayValue;
6 | import graphql.language.BooleanValue;
7 | import graphql.language.EnumValue;
8 | import graphql.language.FloatValue;
9 | import graphql.language.IntValue;
10 | import graphql.language.NullValue;
11 | import graphql.language.ObjectField;
12 | import graphql.language.ObjectValue;
13 | import graphql.language.StringValue;
14 | import graphql.language.Value;
15 | import graphql.language.VariableReference;
16 | import graphql.schema.Coercing;
17 | import graphql.schema.CoercingParseLiteralException;
18 | import graphql.schema.CoercingParseValueException;
19 | import graphql.schema.CoercingSerializeException;
20 | import graphql.schema.GraphQLScalarType;
21 | import graphql.util.FpKit;
22 |
23 | import java.math.BigDecimal;
24 | import java.math.BigInteger;
25 | import java.util.ArrayList;
26 | import java.util.Collections;
27 | import java.util.LinkedHashMap;
28 | import java.util.List;
29 | import java.util.Map;
30 | import java.util.stream.Collectors;
31 |
32 | import static graphql.language.ObjectField.newObjectField;
33 | import static graphql.scalars.util.Kit.typeName;
34 |
35 | /**
36 | * Access this via {@link graphql.scalars.ExtendedScalars#Object}
37 | */
38 | @Internal
39 | public final class ObjectScalar {
40 |
41 | private ObjectScalar() {}
42 |
43 | static final Coercing OBJECT_COERCING = new Coercing() {
44 | @Override
45 | public Object serialize(Object input) throws CoercingSerializeException {
46 | return input;
47 | }
48 |
49 | @Override
50 | public Object parseValue(Object input) throws CoercingParseValueException {
51 | return input;
52 | }
53 |
54 | @Override
55 | public Object parseLiteral(Object input) throws CoercingParseLiteralException {
56 | // on purpose - object scalars can be null
57 | return parseLiteral(input, Collections.emptyMap());
58 | }
59 |
60 | @Override
61 | public Object parseLiteral(Object input, Map variables) throws CoercingParseLiteralException {
62 | if (!(input instanceof Value)) {
63 | throw new CoercingParseLiteralException(
64 | "Expected AST type 'Value' but was '" + typeName(input) + "'."
65 | );
66 | }
67 | if (input instanceof FloatValue) {
68 | return ((FloatValue) input).getValue();
69 | }
70 | if (input instanceof StringValue) {
71 | return ((StringValue) input).getValue();
72 | }
73 | if (input instanceof IntValue) {
74 | return ((IntValue) input).getValue();
75 | }
76 | if (input instanceof BooleanValue) {
77 | return ((BooleanValue) input).isValue();
78 | }
79 | if (input instanceof EnumValue) {
80 | return ((EnumValue) input).getName();
81 | }
82 | if (input instanceof VariableReference) {
83 | String varName = ((VariableReference) input).getName();
84 | return variables.get(varName);
85 | }
86 | if (input instanceof ArrayValue) {
87 | List values = ((ArrayValue) input).getValues();
88 | return values.stream()
89 | .map(v -> parseLiteral(v, variables))
90 | .collect(Collectors.toList());
91 | }
92 | if (input instanceof ObjectValue) {
93 | List values = ((ObjectValue) input).getObjectFields();
94 | Map parsedValues = new LinkedHashMap<>();
95 | values.forEach(fld -> {
96 | Object parsedValue;
97 | if (fld.getValue() instanceof NullValue) { // Nested NullValue inside ObjectValue
98 | parsedValue = null;
99 | } else {
100 | parsedValue = parseLiteral(fld.getValue(), variables);
101 | }
102 | parsedValues.put(fld.getName(), parsedValue);
103 | });
104 | return parsedValues;
105 | }
106 | return Assert.assertShouldNeverHappen("We have covered all Value types");
107 | }
108 |
109 | @Override
110 | public Value> valueToLiteral(Object input) {
111 | if (input == null) {
112 | return NullValue.newNullValue().build();
113 | }
114 | if (input instanceof String) {
115 | return new StringValue((String) input);
116 | }
117 | if (input instanceof Float) {
118 | return new FloatValue(BigDecimal.valueOf((Float) input));
119 | }
120 | if (input instanceof Double) {
121 | return new FloatValue(BigDecimal.valueOf((Double) input));
122 | }
123 | if (input instanceof BigDecimal) {
124 | return new FloatValue((BigDecimal) input);
125 | }
126 | if (input instanceof BigInteger) {
127 | return new IntValue((BigInteger) input);
128 | }
129 | if (input instanceof Number) {
130 | long l = ((Number) input).longValue();
131 | return new IntValue(BigInteger.valueOf(l));
132 | }
133 | if (input instanceof Boolean) {
134 | return new BooleanValue((Boolean) input);
135 | }
136 | if (FpKit.isIterable(input)) {
137 | return handleIterable(FpKit.toIterable(input));
138 | }
139 | if (input instanceof Map) {
140 | return handleMap((Map, ?>) input);
141 | }
142 | throw new UnsupportedOperationException("The ObjectScalar cant handle values of type : " + input.getClass());
143 | }
144 |
145 | private Value> handleMap(Map, ?> map) {
146 | ObjectValue.Builder builder = ObjectValue.newObjectValue();
147 | for (Map.Entry, ?> entry : map.entrySet()) {
148 | String name = String.valueOf(entry.getKey());
149 | Value> value = valueToLiteral(entry.getValue());
150 |
151 | builder.objectField(
152 | newObjectField().name(name).value(value).build()
153 | );
154 | }
155 | return builder.build();
156 | }
157 |
158 | @SuppressWarnings("rawtypes")
159 | private Value> handleIterable(Iterable> input) {
160 | List values = new ArrayList<>();
161 | for (Object val : input) {
162 | values.add(valueToLiteral(val));
163 | }
164 | return ArrayValue.newArrayValue().values(values).build();
165 | }
166 | };
167 |
168 | public static GraphQLScalarType INSTANCE = GraphQLScalarType.newScalar()
169 | .name("Object")
170 | .description("An object scalar")
171 | .coercing(OBJECT_COERCING)
172 | .build();
173 | }
174 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/regex/RegexScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.regex;
2 |
3 | import graphql.Assert;
4 | import graphql.PublicApi;
5 | import graphql.language.StringValue;
6 | import graphql.language.Value;
7 | import graphql.schema.Coercing;
8 | import graphql.schema.CoercingParseLiteralException;
9 | import graphql.schema.CoercingParseValueException;
10 | import graphql.schema.CoercingSerializeException;
11 | import graphql.schema.GraphQLScalarType;
12 |
13 | import java.util.ArrayList;
14 | import java.util.Collections;
15 | import java.util.List;
16 | import java.util.function.Function;
17 | import java.util.regex.Matcher;
18 | import java.util.regex.Pattern;
19 |
20 | import static graphql.scalars.util.Kit.typeName;
21 |
22 | /**
23 | * This is really a scalar factory for creating new scalar String types that are based on a value matching
24 | * a regular expression.
25 | */
26 | @PublicApi
27 | public final class RegexScalar {
28 |
29 | private RegexScalar() {}
30 |
31 | /**
32 | * A builder for {@link graphql.scalars.regex.RegexScalar}
33 | */
34 | public static class Builder {
35 | private String name;
36 | private String description;
37 | private List patterns = new ArrayList<>();
38 |
39 | /**
40 | * Sets the name of the regex scalar
41 | *
42 | * @param name the name of the regex scalar
43 | *
44 | * @return this builder
45 | */
46 | public Builder name(String name) {
47 | this.name = name;
48 | return this;
49 | }
50 |
51 | /**
52 | * Sets the description of the regex scalar
53 | *
54 | * @param description the description of the regex scalar
55 | *
56 | * @return this builder
57 | */
58 | public Builder description(String description) {
59 | this.description = description;
60 | return this;
61 | }
62 |
63 | /**
64 | * Adds a {@link java.util.regex.Pattern} that controls the acceptable value for this scalar
65 | *
66 | * @param pattern the regex pattern
67 | *
68 | * @return this builder
69 | */
70 | public Builder addPattern(Pattern pattern) {
71 | this.patterns.add(pattern);
72 | return this;
73 | }
74 |
75 | /**
76 | * Adds a {@link java.util.regex.Pattern} that controls the acceptable value for this scalar
77 | *
78 | * @param patterns one of more regex patterns
79 | *
80 | * @return this builder
81 | */
82 | public Builder addPatterns(Pattern... patterns) {
83 | Collections.addAll(this.patterns, patterns);
84 | return this;
85 | }
86 |
87 | /**
88 | * @return the built {@link graphql.scalars.regex.RegexScalar}
89 | */
90 | public GraphQLScalarType build() {
91 | Assert.assertNotNull(name);
92 | return regexScalarImpl(name, description, patterns);
93 | }
94 | }
95 |
96 | private static GraphQLScalarType regexScalarImpl(String name, String description, List patterns) {
97 | Assert.assertNotNull(patterns);
98 |
99 | Coercing coercing = new Coercing() {
100 | @Override
101 | public String serialize(Object input) throws CoercingSerializeException {
102 | String value = String.valueOf(input);
103 | return matches(value, CoercingSerializeException::new);
104 | }
105 |
106 | @Override
107 | public String parseValue(Object input) throws CoercingParseValueException {
108 | String value = String.valueOf(input);
109 | return matches(value, CoercingParseValueException::new);
110 | }
111 |
112 | @Override
113 | public String parseLiteral(Object input) throws CoercingParseLiteralException {
114 | if (!(input instanceof StringValue)) {
115 | throw new CoercingParseLiteralException(
116 | "Expected AST type 'StringValue' but was '" + typeName(input) + "'."
117 | );
118 | }
119 | String value = ((StringValue) input).getValue();
120 | return matches(value, CoercingParseLiteralException::new);
121 | }
122 |
123 | @Override
124 | public Value> valueToLiteral(Object input) {
125 | String s = serialize(input);
126 | return StringValue.newStringValue(s).build();
127 | }
128 |
129 |
130 | private String matches(String value, Function exceptionMaker) {
131 | for (Pattern pattern : patterns) {
132 | Matcher matcher = pattern.matcher(value);
133 | if (matcher.matches()) {
134 | return value;
135 | }
136 | }
137 | throw exceptionMaker.apply("Unable to accept a value into the '" + name + "' scalar. It does not match the regular expressions.");
138 | }
139 | };
140 |
141 | return GraphQLScalarType.newScalar()
142 | .name(name)
143 | .description(description)
144 | .coercing(coercing)
145 | .build();
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/url/UrlScalar.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.url;
2 |
3 | import graphql.Internal;
4 | import graphql.language.StringValue;
5 | import graphql.language.Value;
6 | import graphql.schema.Coercing;
7 | import graphql.schema.CoercingParseLiteralException;
8 | import graphql.schema.CoercingParseValueException;
9 | import graphql.schema.CoercingSerializeException;
10 | import graphql.schema.GraphQLScalarType;
11 |
12 | import java.io.File;
13 | import java.net.MalformedURLException;
14 | import java.net.URI;
15 | import java.net.URL;
16 | import java.util.Optional;
17 | import java.util.function.Function;
18 |
19 | import static graphql.scalars.util.Kit.typeName;
20 |
21 | @Internal
22 | public final class UrlScalar {
23 |
24 | private UrlScalar() {}
25 |
26 | public static final GraphQLScalarType INSTANCE;
27 |
28 | static {
29 | Coercing coercing = new Coercing() {
30 | @Override
31 | public URL serialize(Object input) throws CoercingSerializeException {
32 | Optional url;
33 | if (input instanceof String) {
34 | url = Optional.of(parseURL(input.toString(), CoercingSerializeException::new));
35 | } else {
36 | url = toURL(input);
37 | }
38 | if (url.isPresent()) {
39 | return url.get();
40 | }
41 | throw new CoercingSerializeException(
42 | "Expected a 'URL' like object but was '" + typeName(input) + "'."
43 | );
44 | }
45 |
46 | @Override
47 | public URL parseValue(Object input) throws CoercingParseValueException {
48 | String urlStr;
49 | if (input instanceof String) {
50 | urlStr = String.valueOf(input);
51 | } else {
52 | Optional url = toURL(input);
53 | if (!url.isPresent()) {
54 | throw new CoercingParseValueException(
55 | "Expected a 'URL' like object but was '" + typeName(input) + "'."
56 | );
57 | }
58 | return url.get();
59 | }
60 | return parseURL(urlStr, CoercingParseValueException::new);
61 | }
62 |
63 | @Override
64 | public URL parseLiteral(Object input) throws CoercingParseLiteralException {
65 | if (!(input instanceof StringValue)) {
66 | throw new CoercingParseLiteralException(
67 | "Expected AST type 'StringValue' but was '" + typeName(input) + "'."
68 | );
69 | }
70 | return parseURL(((StringValue) input).getValue(), CoercingParseLiteralException::new);
71 | }
72 |
73 | @Override
74 | public Value valueToLiteral(Object input) {
75 | URL url = serialize(input);
76 | return StringValue.newStringValue(url.toExternalForm()).build();
77 | }
78 |
79 |
80 | private URL parseURL(String input, Function exceptionMaker) {
81 | try {
82 | return new URL(input);
83 | } catch (MalformedURLException e) {
84 | throw exceptionMaker.apply("Invalid URL value : '" + input + "'.");
85 | }
86 | }
87 | };
88 |
89 | INSTANCE = GraphQLScalarType.newScalar()
90 | .name("Url")
91 | .description("A Url scalar")
92 | .coercing(coercing)
93 | .build();
94 | }
95 |
96 | private static Optional toURL(Object input) {
97 | if (input instanceof URL) {
98 | return Optional.of((URL) input);
99 | } else if (input instanceof URI) {
100 | try {
101 | return Optional.of(((URI) input).toURL());
102 | } catch (MalformedURLException ignored) {
103 | }
104 | } else if (input instanceof File) {
105 | try {
106 | return Optional.of(((File) input).toURI().toURL());
107 | } catch (MalformedURLException ignored) {
108 | }
109 | }
110 | return Optional.empty();
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/graphql/scalars/util/Kit.java:
--------------------------------------------------------------------------------
1 | package graphql.scalars.util;
2 |
3 | public class Kit {
4 |
5 | public static String typeName(Object input) {
6 | if (input == null) {
7 | return "null";
8 | }
9 | return input.getClass().getSimpleName();
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/alias/AliasedScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.alias
2 |
3 | import graphql.Scalars
4 | import graphql.language.StringValue
5 | import graphql.scalars.ExtendedScalars
6 | import graphql.schema.GraphQLScalarType
7 | import spock.lang.Specification
8 |
9 | class AliasedScalarTest extends Specification {
10 |
11 | GraphQLScalarType socialMediaLink = ExtendedScalars.newAliasedScalar("SocialMediaLink")
12 | .aliasedScalar(Scalars.GraphQLString)
13 | .build()
14 |
15 | def "basic wrapping"() {
16 |
17 | when:
18 | def result = socialMediaLink.coercing.serialize("ABC")
19 | then:
20 | result == "ABC"
21 |
22 | when:
23 | result = socialMediaLink.coercing.parseValue("ABC")
24 | then:
25 | result == "ABC"
26 |
27 | when:
28 | result = socialMediaLink.coercing.parseLiteral(new StringValue("ABC"))
29 | then:
30 | result == "ABC"
31 |
32 | when:
33 | result = socialMediaLink.coercing.parseLiteral(new StringValue("ABC"), [:])
34 | then:
35 | result == "ABC"
36 |
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/country/code/CountryCodeScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.country.code
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseValueException
6 | import spock.lang.Specification
7 | import spock.lang.Unroll
8 |
9 | import static graphql.scalars.util.TestKit.mkCountryCode
10 | import static graphql.scalars.util.TestKit.mkStringValue
11 |
12 | class CountryCodeScalarTest extends Specification {
13 |
14 | def coercing = ExtendedScalars.CountryCode.getCoercing()
15 |
16 | @Unroll
17 | def "invoke parseValue for countryCode"() {
18 | when:
19 | def result = coercing.parseValue(input)
20 | then:
21 | result == expectedValue
22 | where:
23 | input | expectedValue
24 | "US" | mkCountryCode("US")
25 | "IN" | mkCountryCode("IN")
26 | mkCountryCode("US") | mkCountryCode("US")
27 | }
28 |
29 |
30 | @Unroll
31 | def "invoke parseLiteral for countryCode"() {
32 |
33 | when:
34 | def result = coercing.parseLiteral(input)
35 | then:
36 | result == expectedValue
37 | where:
38 | input | expectedValue
39 | new StringValue("GB") | mkCountryCode("GB")
40 | new StringValue("US") | mkCountryCode("US")
41 | new StringValue("IN") | mkCountryCode("IN")
42 | }
43 |
44 | @Unroll
45 | def "invoke serialize with countryCode"() {
46 | when:
47 | def result = coercing.serialize(input)
48 | then:
49 | result == expectedValue
50 | where:
51 | input | expectedValue
52 | "GB" | "GB"
53 | "US" | "US"
54 | "IN" | "IN"
55 | mkCountryCode("US") | "US"
56 | }
57 |
58 | @Unroll
59 | def "invoke valueToLiteral with countryCode"() {
60 |
61 | when:
62 | def result = coercing.valueToLiteral(input)
63 | then:
64 | result.isEqualTo(expectedValue)
65 | where:
66 | input | expectedValue
67 | "GB" | mkStringValue("GB")
68 | "US" | mkStringValue("US")
69 | "IN" | mkStringValue("IN")
70 | mkCountryCode("US") | mkStringValue("US")
71 | }
72 |
73 | @Unroll
74 | def "parseValue throws exception for invalid input #value"() {
75 | when:
76 | coercing.parseValue(value)
77 | then:
78 | thrown(CoercingParseValueException)
79 |
80 | where:
81 | value | _
82 | "" | _
83 | "US(UNITED STATES)" | _
84 | "not a countryCode " | _
85 | "42.3" | _
86 | new Double(42.3) | _
87 | new Float(42.3) | _
88 | new Object() | _
89 | }
90 |
91 |
92 | @Unroll
93 | def "invoke parseValue with all countryCode list"() {
94 | when:
95 | def result = coercing.parseValue(input)
96 | then:
97 | result == expectedValue
98 | where:
99 | input | expectedValue
100 | "GB" | mkCountryCode("GB")
101 | "US" | mkCountryCode("US")
102 | "IN" | mkCountryCode("IN")
103 | "AF" | mkCountryCode("AF")
104 | "AX" | mkCountryCode("AX")
105 | "AL" | mkCountryCode("AL")
106 | "DZ" | mkCountryCode("DZ")
107 | "AS" | mkCountryCode("AS")
108 | "AD" | mkCountryCode("AD")
109 | "AO" | mkCountryCode("AO")
110 | "AI" | mkCountryCode("AI")
111 | "AQ" | mkCountryCode("AQ")
112 | "AG" | mkCountryCode("AG")
113 | "AR" | mkCountryCode("AR")
114 | "AM" | mkCountryCode("AM")
115 | "AW" | mkCountryCode("AW")
116 | "AU" | mkCountryCode("AU")
117 | "AT" | mkCountryCode("AT")
118 | "AZ" | mkCountryCode("AZ")
119 | "BS" | mkCountryCode("BS")
120 | "BH" | mkCountryCode("BH")
121 | "BD" | mkCountryCode("BD")
122 | "BB" | mkCountryCode("BB")
123 | "BY" | mkCountryCode("BY")
124 | "BE" | mkCountryCode("BE")
125 | "BZ" | mkCountryCode("BZ")
126 | "BJ" | mkCountryCode("BJ")
127 | "BM" | mkCountryCode("BM")
128 | "BT" | mkCountryCode("BT")
129 | "BO" | mkCountryCode("BO")
130 | "BQ" | mkCountryCode("BQ")
131 | "BA" | mkCountryCode("BA")
132 | "BW" | mkCountryCode("BW")
133 | "BV" | mkCountryCode("BV")
134 | "BR" | mkCountryCode("BR")
135 | "IO" | mkCountryCode("IO")
136 | "BN" | mkCountryCode("BN")
137 | "BG" | mkCountryCode("BG")
138 | "BF" | mkCountryCode("BF")
139 | "BI" | mkCountryCode("BI")
140 | "KH" | mkCountryCode("KH")
141 | "CM" | mkCountryCode("CM")
142 | "CA" | mkCountryCode("CA")
143 | "CV" | mkCountryCode("CV")
144 | "KY" | mkCountryCode("KY")
145 | "CF" | mkCountryCode("CF")
146 | "TD" | mkCountryCode("TD")
147 | "CL" | mkCountryCode("CL")
148 | "CN" | mkCountryCode("CN")
149 | "CX" | mkCountryCode("CX")
150 | "CC" | mkCountryCode("CC")
151 | "CO" | mkCountryCode("CO")
152 | "KM" | mkCountryCode("KM")
153 | "CG" | mkCountryCode("CG")
154 | "CD" | mkCountryCode("CD")
155 | "CK" | mkCountryCode("CK")
156 | "CR" | mkCountryCode("CR")
157 | "CI" | mkCountryCode("CI")
158 | "HR" | mkCountryCode("HR")
159 | "CU" | mkCountryCode("CU")
160 | "CW" | mkCountryCode("CW")
161 | "CY" | mkCountryCode("CY")
162 | "CZ" | mkCountryCode("CZ")
163 | "DK" | mkCountryCode("DK")
164 | "DJ" | mkCountryCode("DJ")
165 | "DM" | mkCountryCode("DM")
166 | "DO" | mkCountryCode("DO")
167 | "EC" | mkCountryCode("EC")
168 | "EG" | mkCountryCode("EG")
169 | "SV" | mkCountryCode("SV")
170 | "GQ" | mkCountryCode("GQ")
171 | "ER" | mkCountryCode("ER")
172 | "EE" | mkCountryCode("EE")
173 | "ET" | mkCountryCode("ET")
174 | "FK" | mkCountryCode("FK")
175 | "FO" | mkCountryCode("FO")
176 | "FJ" | mkCountryCode("FJ")
177 | "FI" | mkCountryCode("FI")
178 | "FR" | mkCountryCode("FR")
179 | "GF" | mkCountryCode("GF")
180 | "PF" | mkCountryCode("PF")
181 | "TF" | mkCountryCode("TF")
182 | "GA" | mkCountryCode("GA")
183 | "GM" | mkCountryCode("GM")
184 | "GE" | mkCountryCode("GE")
185 | "DE" | mkCountryCode("DE")
186 | "GH" | mkCountryCode("GH")
187 | "GI" | mkCountryCode("GI")
188 | "GR" | mkCountryCode("GR")
189 | "GL" | mkCountryCode("GL")
190 | "GD" | mkCountryCode("GD")
191 | "GP" | mkCountryCode("GP")
192 | "GU" | mkCountryCode("GU")
193 | "GT" | mkCountryCode("GT")
194 | "GG" | mkCountryCode("GG")
195 | "GN" | mkCountryCode("GN")
196 | "GW" | mkCountryCode("GW")
197 | "GY" | mkCountryCode("GY")
198 | "HT" | mkCountryCode("HT")
199 | "HM" | mkCountryCode("HM")
200 | "VA" | mkCountryCode("VA")
201 | "HN" | mkCountryCode("HN")
202 | "HK" | mkCountryCode("HK")
203 | "HU" | mkCountryCode("HU")
204 | "IS" | mkCountryCode("IS")
205 | "ID" | mkCountryCode("ID")
206 | "IR" | mkCountryCode("IR")
207 | "IQ" | mkCountryCode("IQ")
208 | "IE" | mkCountryCode("IE")
209 | "IM" | mkCountryCode("IM")
210 | "IL" | mkCountryCode("IL")
211 | "IT" | mkCountryCode("IT")
212 | "JM" | mkCountryCode("JM")
213 | "JP" | mkCountryCode("JP")
214 | "JE" | mkCountryCode("JE")
215 | "JO" | mkCountryCode("JO")
216 | "KZ" | mkCountryCode("KZ")
217 | "KE" | mkCountryCode("KE")
218 | "KI" | mkCountryCode("KI")
219 | "KP" | mkCountryCode("KP")
220 | "KR" | mkCountryCode("KR")
221 | "KW" | mkCountryCode("KW")
222 | "KG" | mkCountryCode("KG")
223 | "LA" | mkCountryCode("LA")
224 | "LV" | mkCountryCode("LV")
225 | "LB" | mkCountryCode("LB")
226 | "LS" | mkCountryCode("LS")
227 | "LR" | mkCountryCode("LR")
228 | "LY" | mkCountryCode("LY")
229 | "LI" | mkCountryCode("LI")
230 | "LT" | mkCountryCode("LT")
231 | "LU" | mkCountryCode("LU")
232 | "MO" | mkCountryCode("MO")
233 | "MK" | mkCountryCode("MK")
234 | "MG" | mkCountryCode("MG")
235 | "MW" | mkCountryCode("MW")
236 | "MY" | mkCountryCode("MY")
237 | "MV" | mkCountryCode("MV")
238 | "ML" | mkCountryCode("ML")
239 | "MT" | mkCountryCode("MT")
240 | "MH" | mkCountryCode("MH")
241 | "MQ" | mkCountryCode("MQ")
242 | "MR" | mkCountryCode("MR")
243 | "MU" | mkCountryCode("MU")
244 | "YT" | mkCountryCode("YT")
245 | "MX" | mkCountryCode("MX")
246 | "FM" | mkCountryCode("FM")
247 | "MD" | mkCountryCode("MD")
248 | "MC" | mkCountryCode("MC")
249 | "MN" | mkCountryCode("MN")
250 | "ME" | mkCountryCode("ME")
251 | "MS" | mkCountryCode("MS")
252 | "MA" | mkCountryCode("MA")
253 | "MZ" | mkCountryCode("MZ")
254 | "MM" | mkCountryCode("MM")
255 | "NA" | mkCountryCode("NA")
256 | "NR" | mkCountryCode("NR")
257 | "NP" | mkCountryCode("NP")
258 | "NL" | mkCountryCode("NL")
259 | "NC" | mkCountryCode("NC")
260 | "NZ" | mkCountryCode("NZ")
261 | "NI" | mkCountryCode("NI")
262 | "NE" | mkCountryCode("NE")
263 | "NG" | mkCountryCode("NG")
264 | "NU" | mkCountryCode("NU")
265 | "NF" | mkCountryCode("NF")
266 | "MP" | mkCountryCode("MP")
267 | "NO" | mkCountryCode("NO")
268 | "OM" | mkCountryCode("OM")
269 | "PK" | mkCountryCode("PK")
270 | "PW" | mkCountryCode("PW")
271 | "PS" | mkCountryCode("PS")
272 | "PA" | mkCountryCode("PA")
273 | "PG" | mkCountryCode("PG")
274 | "PY" | mkCountryCode("PY")
275 | "PE" | mkCountryCode("PE")
276 | "PH" | mkCountryCode("PH")
277 | "PN" | mkCountryCode("PN")
278 | "PL" | mkCountryCode("PL")
279 | "PT" | mkCountryCode("PT")
280 | "PR" | mkCountryCode("PR")
281 | "QA" | mkCountryCode("QA")
282 | "RE" | mkCountryCode("RE")
283 | "RO" | mkCountryCode("RO")
284 | "RU" | mkCountryCode("RU")
285 | "RW" | mkCountryCode("RW")
286 | "BL" | mkCountryCode("BL")
287 | "SH" | mkCountryCode("SH")
288 | "KN" | mkCountryCode("KN")
289 | "LC" | mkCountryCode("LC")
290 | "MF" | mkCountryCode("MF")
291 | "PM" | mkCountryCode("PM")
292 | "VC" | mkCountryCode("VC")
293 | "WS" | mkCountryCode("WS")
294 | "SM" | mkCountryCode("SM")
295 | "ST" | mkCountryCode("ST")
296 | "SA" | mkCountryCode("SA")
297 | "SN" | mkCountryCode("SN")
298 | "RS" | mkCountryCode("RS")
299 | "SC" | mkCountryCode("SC")
300 | "SL" | mkCountryCode("SL")
301 | "SG" | mkCountryCode("SG")
302 | "SX" | mkCountryCode("SX")
303 | "SK" | mkCountryCode("SK")
304 | "SI" | mkCountryCode("SI")
305 | "SB" | mkCountryCode("SB")
306 | "SO" | mkCountryCode("SO")
307 | "ZA" | mkCountryCode("ZA")
308 | "GS" | mkCountryCode("GS")
309 | "SS" | mkCountryCode("SS")
310 | "ES" | mkCountryCode("ES")
311 | "LK" | mkCountryCode("LK")
312 | "SD" | mkCountryCode("SD")
313 | "SR" | mkCountryCode("SR")
314 | "SJ" | mkCountryCode("SJ")
315 | "SZ" | mkCountryCode("SZ")
316 | "SE" | mkCountryCode("SE")
317 | "CH" | mkCountryCode("CH")
318 | "SY" | mkCountryCode("SY")
319 | "TW" | mkCountryCode("TW")
320 | "TJ" | mkCountryCode("TJ")
321 | "TZ" | mkCountryCode("TZ")
322 | "TH" | mkCountryCode("TH")
323 | "TL" | mkCountryCode("TL")
324 | "TG" | mkCountryCode("TG")
325 | "TK" | mkCountryCode("TK")
326 | "TO" | mkCountryCode("TO")
327 | "TT" | mkCountryCode("TT")
328 | "TN" | mkCountryCode("TN")
329 | "TR" | mkCountryCode("TR")
330 | "TM" | mkCountryCode("TM")
331 | "TC" | mkCountryCode("TC")
332 | "TV" | mkCountryCode("TV")
333 | "UG" | mkCountryCode("UG")
334 | "UA" | mkCountryCode("UA")
335 | "AE" | mkCountryCode("AE")
336 | "UM" | mkCountryCode("UM")
337 | "UY" | mkCountryCode("UY")
338 | "UZ" | mkCountryCode("UZ")
339 | "VU" | mkCountryCode("VU")
340 | "VE" | mkCountryCode("VE")
341 | "VN" | mkCountryCode("VN")
342 | "VG" | mkCountryCode("VG")
343 | "VI" | mkCountryCode("VI")
344 | "WF" | mkCountryCode("WF")
345 | "EH" | mkCountryCode("EH")
346 | "YE" | mkCountryCode("YE")
347 | "ZM" | mkCountryCode("ZM")
348 | "ZW" | mkCountryCode("ZW")
349 | }
350 |
351 | }
352 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/currency/CurrencyScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.currency
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseValueException
6 | import spock.lang.Specification
7 | import spock.lang.Unroll
8 |
9 | import static graphql.scalars.util.TestKit.mkCurrency
10 | import static graphql.scalars.util.TestKit.mkStringValue
11 |
12 | class CurrencyScalarTest extends Specification {
13 |
14 |
15 | def coercing = ExtendedScalars.Currency.getCoercing()
16 |
17 | @Unroll
18 | def "currency parseValue cases"() {
19 |
20 | when:
21 | def result = coercing.parseValue(input)
22 | then:
23 | result == expectedValue
24 | where:
25 | input | expectedValue
26 |
27 | "USD" | mkCurrency("USD")
28 | mkCurrency("USD") | mkCurrency("USD")
29 | "GBP" | mkCurrency("GBP")
30 | "EUR" | mkCurrency("EUR")
31 | "CNY" | mkCurrency("CNY")
32 | "ARS" | mkCurrency("ARS")
33 | mkCurrency("ARS") | mkCurrency("ARS")
34 | mkCurrency("ALL") | mkCurrency("ALL")
35 | mkCurrency("AMD") | mkCurrency("AMD")
36 | mkCurrency("ANG") | mkCurrency("ANG")
37 | mkCurrency("AOA") | mkCurrency("AOA")
38 | }
39 |
40 |
41 | @Unroll
42 | def "currency parseLiteral"() {
43 |
44 | when:
45 | def result = coercing.parseLiteral(input)
46 | then:
47 | result == expectedValue
48 | where:
49 | input | expectedValue
50 | new StringValue("EUR") | mkCurrency("EUR")
51 | new StringValue("USD") | mkCurrency("USD")
52 | new StringValue("GBP") | mkCurrency("GBP")
53 | }
54 |
55 | @Unroll
56 | def "currency serialize"() {
57 |
58 | when:
59 | def result = coercing.serialize(input)
60 | then:
61 | result == expectedValue
62 | where:
63 | input | expectedValue
64 | "USD" | "USD"
65 | mkCurrency("USD") | "USD"
66 | }
67 |
68 | @Unroll
69 | def "currency valueToLiteral"() {
70 |
71 | when:
72 | def result = coercing.valueToLiteral(input)
73 | then:
74 | result.isEqualTo(expectedValue)
75 | where:
76 | input | expectedValue
77 | "USD" | mkStringValue("USD")
78 | mkCurrency("USD") | mkStringValue("USD")
79 | }
80 |
81 | @Unroll
82 | def "parseValue throws exception for invalid input #value"() {
83 | when:
84 | coercing.parseValue(value)
85 | then:
86 | thrown(CoercingParseValueException)
87 |
88 | where:
89 | value | _
90 | "" | _
91 | "US_DOLLAR" | _
92 | "not a currency " | _
93 | "42.3" | _
94 | new Double(42.3) | _
95 | new Float(42.3) | _
96 | new Object() | _
97 | }
98 |
99 |
100 | @Unroll
101 | def "all currency ISO list parseValue"() {
102 |
103 | when:
104 | def result = coercing.parseValue(input)
105 | then:
106 | result == expectedValue
107 | where:
108 | input | expectedValue
109 |
110 | "USD" | mkCurrency("USD")
111 | "EUR" | mkCurrency("EUR")
112 | "GBP" | mkCurrency("GBP")
113 | "CNY" | mkCurrency("CNY")
114 | "AED" | mkCurrency("AED")
115 | "AFN" | mkCurrency("AFN")
116 | "ALL" | mkCurrency("ALL")
117 | "AMD" | mkCurrency("AMD")
118 | "ANG" | mkCurrency("ANG")
119 | "AOA" | mkCurrency("AOA")
120 | "ARS" | mkCurrency("ARS")
121 | "AUD" | mkCurrency("AUD")
122 | "AWG" | mkCurrency("AWG")
123 | "AZN" | mkCurrency("AZN")
124 | "BAM" | mkCurrency("BAM")
125 | "BBD" | mkCurrency("BBD")
126 | "BDT" | mkCurrency("BDT")
127 | "BGN" | mkCurrency("BGN")
128 | "BHD" | mkCurrency("BHD")
129 | "BIF" | mkCurrency("BIF")
130 | "BMD" | mkCurrency("BMD")
131 | "BND" | mkCurrency("BND")
132 | "BOB" | mkCurrency("BOB")
133 | "BOV" | mkCurrency("BOV")
134 | "BRL" | mkCurrency("BRL")
135 | "BSD" | mkCurrency("BSD")
136 | "BTN" | mkCurrency("BTN")
137 | "BWP" | mkCurrency("BWP")
138 | "BYN" | mkCurrency("BYN")
139 | "BZD" | mkCurrency("BZD")
140 | "CAD" | mkCurrency("CAD")
141 | "CDF" | mkCurrency("CDF")
142 | "CHE" | mkCurrency("CHE")
143 | "CHF" | mkCurrency("CHF")
144 | "CHW" | mkCurrency("CHW")
145 | "CLF" | mkCurrency("CLF")
146 | "CLP" | mkCurrency("CLP")
147 | "COP" | mkCurrency("COP")
148 | "COU" | mkCurrency("COU")
149 | "CRC" | mkCurrency("CRC")
150 | "CUC" | mkCurrency("CUC")
151 | "CUP" | mkCurrency("CUP")
152 | "CVE" | mkCurrency("CVE")
153 | "CZK" | mkCurrency("CZK")
154 | "DJF" | mkCurrency("DJF")
155 | "DKK" | mkCurrency("DKK")
156 | "DOP" | mkCurrency("DOP")
157 | "DZD" | mkCurrency("DZD")
158 | "EGP" | mkCurrency("EGP")
159 | "ERN" | mkCurrency("ERN")
160 | "ETB" | mkCurrency("ETB")
161 | "FJD" | mkCurrency("FJD")
162 | "FKP" | mkCurrency("FKP")
163 | "GEL" | mkCurrency("GEL")
164 | "GHS" | mkCurrency("GHS")
165 | "GIP" | mkCurrency("GIP")
166 | "GMD" | mkCurrency("GMD")
167 | "GNF" | mkCurrency("GNF")
168 | "GTQ" | mkCurrency("GTQ")
169 | "GYD" | mkCurrency("GYD")
170 | "HKD" | mkCurrency("HKD")
171 | "HNL" | mkCurrency("HNL")
172 | "HRK" | mkCurrency("HRK")
173 | "HTG" | mkCurrency("HTG")
174 | "HUF" | mkCurrency("HUF")
175 | "IDR" | mkCurrency("IDR")
176 | "ILS" | mkCurrency("ILS")
177 | "INR" | mkCurrency("INR")
178 | "IQD" | mkCurrency("IQD")
179 | "IRR" | mkCurrency("IRR")
180 | "ISK" | mkCurrency("ISK")
181 | "JMD" | mkCurrency("JMD")
182 | "JOD" | mkCurrency("JOD")
183 | "JPY" | mkCurrency("JPY")
184 | "KES" | mkCurrency("KES")
185 | "KGS" | mkCurrency("KGS")
186 | "KHR" | mkCurrency("KHR")
187 | "KMF" | mkCurrency("KMF")
188 | "KPW" | mkCurrency("KPW")
189 | "KRW" | mkCurrency("KRW")
190 | "KWD" | mkCurrency("KWD")
191 | "KYD" | mkCurrency("KYD")
192 | "KZT" | mkCurrency("KZT")
193 | "LAK" | mkCurrency("LAK")
194 | "LBP" | mkCurrency("LBP")
195 | "LKR" | mkCurrency("LKR")
196 | "LRD" | mkCurrency("LRD")
197 | "LSL" | mkCurrency("LSL")
198 | "LYD" | mkCurrency("LYD")
199 | "MAD" | mkCurrency("MAD")
200 | "MDL" | mkCurrency("MDL")
201 | "MGA" | mkCurrency("MGA")
202 | "MKD" | mkCurrency("MKD")
203 | "MMK" | mkCurrency("MMK")
204 | "MNT" | mkCurrency("MNT")
205 | "MOP" | mkCurrency("MOP")
206 | "MRU" | mkCurrency("MRU")
207 | "MUR" | mkCurrency("MUR")
208 | "MVR" | mkCurrency("MVR")
209 | "MWK" | mkCurrency("MWK")
210 | "MXN" | mkCurrency("MXN")
211 | "MXV" | mkCurrency("MXV")
212 | "MYR" | mkCurrency("MYR")
213 | "MZN" | mkCurrency("MZN")
214 | "NAD" | mkCurrency("NAD")
215 | "NGN" | mkCurrency("NGN")
216 | "NIO" | mkCurrency("NIO")
217 | "NOK" | mkCurrency("NOK")
218 | "NPR" | mkCurrency("NPR")
219 | "NZD" | mkCurrency("NZD")
220 | "OMR" | mkCurrency("OMR")
221 | "PAB" | mkCurrency("PAB")
222 | "PEN" | mkCurrency("PEN")
223 | "PGK" | mkCurrency("PGK")
224 | "PHP" | mkCurrency("PHP")
225 | "PKR" | mkCurrency("PKR")
226 | "PLN" | mkCurrency("PLN")
227 | "PYG" | mkCurrency("PYG")
228 | "QAR" | mkCurrency("QAR")
229 | "RON" | mkCurrency("RON")
230 | "RSD" | mkCurrency("RSD")
231 | "RWF" | mkCurrency("RWF")
232 | "RUB" | mkCurrency("RUB")
233 | "SAR" | mkCurrency("SAR")
234 | "SBD" | mkCurrency("SBD")
235 | "SCR" | mkCurrency("SCR")
236 | "SDG" | mkCurrency("SDG")
237 | "SEK" | mkCurrency("SEK")
238 | "SGD" | mkCurrency("SGD")
239 | "SHP" | mkCurrency("SHP")
240 | "SLL" | mkCurrency("SLL")
241 | "SOS" | mkCurrency("SOS")
242 | "SRD" | mkCurrency("SRD")
243 | "SSP" | mkCurrency("SSP")
244 | "STN" | mkCurrency("STN")
245 | "SVC" | mkCurrency("SVC")
246 | "SYP" | mkCurrency("SYP")
247 | "SZL" | mkCurrency("SZL")
248 | "THB" | mkCurrency("THB")
249 | "TJS" | mkCurrency("TJS")
250 | "TMT" | mkCurrency("TMT")
251 | "TND" | mkCurrency("TND")
252 | "TOP" | mkCurrency("TOP")
253 | "TRY" | mkCurrency("TRY")
254 | "TTD" | mkCurrency("TTD")
255 | "TWD" | mkCurrency("TWD")
256 | "TZS" | mkCurrency("TZS")
257 | "UAH" | mkCurrency("UAH")
258 | "UGX" | mkCurrency("UGX")
259 | "USN" | mkCurrency("USN")
260 | "UYI" | mkCurrency("UYI")
261 | "UYU" | mkCurrency("UYU")
262 | "UZS" | mkCurrency("UZS")
263 | "VEF" | mkCurrency("VEF")
264 | "VND" | mkCurrency("VND")
265 | "VUV" | mkCurrency("VUV")
266 | "WST" | mkCurrency("WST")
267 | "XAF" | mkCurrency("XAF")
268 | "XCD" | mkCurrency("XCD")
269 | "XDR" | mkCurrency("XDR")
270 | "XOF" | mkCurrency("XOF")
271 | "XPF" | mkCurrency("XPF")
272 | "XSU" | mkCurrency("XSU")
273 | "XUA" | mkCurrency("XUA")
274 | "YER" | mkCurrency("YER")
275 | "ZAR" | mkCurrency("ZAR")
276 | "ZMW" | mkCurrency("ZMW")
277 | "ZWL" | mkCurrency("ZWL")
278 | }
279 |
280 |
281 | }
282 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/datetime/DateScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.datetime
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import spock.lang.Specification
6 | import spock.lang.Unroll
7 |
8 | import static graphql.scalars.util.TestKit.mkLocalDate
9 | import static graphql.scalars.util.TestKit.mkOffsetDT
10 | import static graphql.scalars.util.TestKit.mkStringValue
11 | import static graphql.scalars.util.TestKit.mkZonedDT
12 |
13 | class DateScalarTest extends Specification {
14 |
15 | def coercing = ExtendedScalars.Date.getCoercing()
16 |
17 | @Unroll
18 | def "full date parseValue"() {
19 |
20 | when:
21 | def result = coercing.parseValue(input)
22 | then:
23 | result == expectedValue
24 | where:
25 | input | expectedValue
26 | "1937-01-01" | mkLocalDate("1937-01-01")
27 | mkOffsetDT(year: 1980, hour: 3) | mkLocalDate("1980-08-08")
28 | mkZonedDT(year: 1980, hour: 3) | mkLocalDate("1980-08-08")
29 | }
30 |
31 | @Unroll
32 | def "full date parseLiteral"() {
33 |
34 | when:
35 | def result = coercing.parseLiteral(input)
36 | then:
37 | result == expectedValue
38 | where:
39 | input | expectedValue
40 | new StringValue("1937-01-01") | mkLocalDate("1937-01-01")
41 | }
42 |
43 | @Unroll
44 | def "full date serialize"() {
45 |
46 | when:
47 | def result = coercing.serialize(input)
48 | then:
49 | result == expectedValue
50 | where:
51 | input | expectedValue
52 | "1937-01-01" | "1937-01-01"
53 | mkOffsetDT(year: 1980, hour: 3) | "1980-08-08"
54 | mkZonedDT(year: 1980, hour: 3) | "1980-08-08"
55 | }
56 |
57 | @Unroll
58 | def "full date valueToLiteral"() {
59 |
60 | when:
61 | def result = coercing.valueToLiteral(input)
62 | then:
63 | result.isEqualTo(expectedValue)
64 | where:
65 | input | expectedValue
66 | "1937-01-01" | mkStringValue("1937-01-01")
67 | mkOffsetDT(year: 1980, hour: 3) | mkStringValue("1980-08-08")
68 | mkZonedDT(year: 1980, hour: 3) | mkStringValue("1980-08-08")
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/datetime/DateTimeScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.datetime
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseLiteralException
6 | import graphql.schema.CoercingParseValueException
7 | import graphql.schema.CoercingSerializeException
8 | import spock.lang.Specification
9 | import spock.lang.Unroll
10 |
11 | import static graphql.scalars.util.TestKit.mkLocalDT
12 | import static graphql.scalars.util.TestKit.mkOffsetDT
13 | import static graphql.scalars.util.TestKit.mkStringValue
14 | import static graphql.scalars.util.TestKit.mkZonedDT
15 |
16 | class DateTimeScalarTest extends Specification {
17 |
18 | def coercing = ExtendedScalars.DateTime.getCoercing()
19 |
20 | @Unroll
21 | def "datetime parseValue"() {
22 |
23 | when:
24 | def result = coercing.parseValue(input)
25 | then:
26 | result == expectedValue
27 | where:
28 | input | expectedValue
29 | "1985-04-12T23:20:50.52Z" | mkOffsetDT("1985-04-12T23:20:50.52Z")
30 | "1996-12-19T16:39:57-08:00" | mkOffsetDT("1996-12-19T16:39:57-08:00")
31 | "1937-01-01T12:00:27.87+00:20" | mkOffsetDT("1937-01-01T12:00:27.87+00:20")
32 | "2022-11-24T01:00:01.02+00:00" | mkOffsetDT("2022-11-24T01:00:01.02+00:00")
33 | mkOffsetDT(year: 1980, hour: 3) | mkOffsetDT("1980-08-08T03:10:09+10:00")
34 | mkZonedDT(year: 1980, hour: 3) | mkOffsetDT("1980-08-08T03:10:09+10:00")
35 | }
36 |
37 | @Unroll
38 | def "datetime valueToLiteral"() {
39 |
40 | when:
41 | def result = coercing.valueToLiteral(input)
42 | then:
43 | result.isEqualTo(expectedValue)
44 | where:
45 | input | expectedValue
46 | "1985-04-12T23:20:50.52Z" | mkStringValue("1985-04-12T23:20:50.520Z")
47 | "1996-12-19T16:39:57-08:00" | mkStringValue("1996-12-19T16:39:57.000-08:00")
48 | "1937-01-01T12:00:27.87+00:20" | mkStringValue("1937-01-01T12:00:27.870+00:20")
49 | "1937-01-01T12:00+00:20" | mkStringValue("1937-01-01T12:00:00.000+00:20")
50 | "2022-11-24T01:00:01.02+00:00" | mkStringValue("2022-11-24T01:00:01.020Z")
51 | mkOffsetDT(year: 1980, hour: 3) | mkStringValue("1980-08-08T03:10:09.000+10:00")
52 | mkZonedDT(year: 1980, hour: 3) | mkStringValue("1980-08-08T03:10:09.000+10:00")
53 | }
54 |
55 | @Unroll
56 | def "datetime parseValue bad inputs"() {
57 |
58 | when:
59 | coercing.parseValue(input)
60 | then:
61 | thrown(expectedValue)
62 | where:
63 | input | expectedValue
64 | "1985-04-12" | CoercingParseValueException // No time provided
65 | "2022-11-24T01:00:01.02-00:00" | CoercingParseValueException // -00:00 is not a valid offset in specification
66 | mkLocalDT(year: 1980, hour: 3) | CoercingParseValueException // LocalDateTime has no time zone
67 | 666 | CoercingParseValueException // A random number
68 | "2011-08-30T13:22:53.108" | CoercingParseValueException // No offset provided
69 | "2011-08-30T24:22:53.108Z" | CoercingParseValueException // 24 is not allowed as hour of the time
70 | "2010-02-30T21:22:53.108Z" | CoercingParseValueException // 30th of February is not a valid date
71 | "2010-02-11T21:22:53.108Z+25:11" | CoercingParseValueException // 25 is not a valid hour for offset
72 | }
73 |
74 | def "datetime AST literal"() {
75 |
76 | when:
77 | def result = coercing.parseLiteral(input)
78 | then:
79 | result == expectedValue
80 | where:
81 | input | expectedValue
82 | new StringValue("1985-04-12T23:20:50.52Z") | mkOffsetDT("1985-04-12T23:20:50.52Z")
83 | }
84 |
85 | def "datetime serialisation"() {
86 |
87 | when:
88 | def result = coercing.serialize(input)
89 | then:
90 | result == expectedValue
91 | where:
92 | input | expectedValue
93 | "1985-04-12T23:20:50.52Z" | "1985-04-12T23:20:50.520Z"
94 | "1996-12-19T16:39:57-08:00" | "1996-12-19T16:39:57.000-08:00"
95 | "1937-01-01T12:00:27.87+00:20" | "1937-01-01T12:00:27.870+00:20"
96 | "2022-11-24T01:00:01.02+00:00" | "2022-11-24T01:00:01.020Z"
97 | mkOffsetDT(year: 1980, hour: 3) | "1980-08-08T03:10:09.000+10:00"
98 | mkZonedDT(year: 1980, hour: 3) | "1980-08-08T03:10:09.000+10:00"
99 | }
100 |
101 | def "datetime serialisation bad inputs"() {
102 |
103 | when:
104 | coercing.serialize(input)
105 | then:
106 | thrown(expectedValue)
107 | where:
108 | input | expectedValue
109 | "1985-04-12" | CoercingSerializeException // No time provided
110 | "2022-11-24T01:00:01.02-00:00" | CoercingSerializeException // -00:00 is not a valid offset in specification
111 | mkLocalDT(year: 1980, hour: 3) | CoercingSerializeException // LocalDateTime has no time zone
112 | 666 | CoercingSerializeException // A random number
113 | "2011-08-30T13:22:53.108" | CoercingSerializeException // No offset provided
114 | "2011-08-30T24:22:53.108Z" | CoercingSerializeException // 24 is not allowed as hour of the time
115 | "2010-02-30T21:22:53.108Z" | CoercingSerializeException // 30th of February is not a valid date
116 | "2010-02-11T21:22:53.108Z+25:11" | CoercingSerializeException // 25 is not a valid hour for offset
117 | }
118 |
119 | @Unroll
120 | def "datetime parseLiteral bad inputs"() {
121 |
122 | when:
123 | coercing.parseLiteral(input)
124 | then:
125 | thrown(expectedValue)
126 | where:
127 | input | expectedValue
128 | "2022-11-24T01:00:01.02-00:00" | CoercingParseLiteralException // -00:00 is not a valid offset in specification
129 | "1985-04-12" | CoercingParseLiteralException // No time provided
130 | "2022-11-24T01:00:01.02-00:00" | CoercingParseLiteralException // -00:00 is not a valid offset in specification
131 | mkLocalDT(year: 1980, hour: 3) | CoercingParseLiteralException // LocalDateTime has no time zone
132 | 666 | CoercingParseLiteralException // A random number
133 | "2011-08-30T13:22:53.108" | CoercingParseLiteralException // No offset provided
134 | "2011-08-30T24:22:53.108Z" | CoercingParseLiteralException // 24 is not allowed as hour of the time
135 | "2010-02-30T21:22:53.108Z" | CoercingParseLiteralException // 30th of February is not a valid date
136 | "2010-02-11T21:22:53.108Z+25:11" | CoercingParseLiteralException // 25 is not a valid hour for offset
137 | }
138 |
139 | }
140 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/datetime/LocalTimeScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.datetime
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseValueException
6 | import graphql.schema.CoercingSerializeException
7 | import spock.lang.Specification
8 | import spock.lang.Unroll
9 |
10 | import static graphql.scalars.util.TestKit.mkLocalT
11 |
12 | class LocalTimeScalarTest extends Specification {
13 |
14 | def coercing = ExtendedScalars.LocalTime.getCoercing()
15 |
16 | @Unroll
17 | def "localtime parseValue"() {
18 |
19 | when:
20 | def result = coercing.parseValue(input)
21 | then:
22 | result == expectedValue
23 | where:
24 | input | expectedValue
25 | "23:20:50.123456789" | mkLocalT("23:20:50.123456789")
26 | "16:39:57.000000000" | mkLocalT("16:39:57")
27 | "16:39:57.0" | mkLocalT("16:39:57")
28 | "16:39:57" | mkLocalT("16:39:57")
29 | }
30 |
31 | @Unroll
32 | def "localtime parseValue bad inputs"() {
33 |
34 | when:
35 | coercing.parseValue(input)
36 | then:
37 | thrown(expectedValue)
38 | where:
39 | input | expectedValue
40 | "23:20:50.52Z" | CoercingParseValueException
41 | "16:39:57-08:00" | CoercingParseValueException
42 | 666 || CoercingParseValueException
43 | }
44 |
45 | def "localtime AST literal"() {
46 |
47 | when:
48 | def result = coercing.parseLiteral(input)
49 | then:
50 | result == expectedValue
51 | where:
52 | input | expectedValue
53 | new StringValue("23:20:50.123456789") | mkLocalT("23:20:50.123456789")
54 | new StringValue("16:39:57.000000000") | mkLocalT("16:39:57")
55 | new StringValue("16:39:57.0") | mkLocalT("16:39:57")
56 | new StringValue("16:39:57") | mkLocalT("16:39:57")
57 | }
58 |
59 | def "localtime serialisation"() {
60 |
61 | when:
62 | def result = coercing.serialize(input)
63 | then:
64 | result == expectedValue
65 | where:
66 | input | expectedValue
67 | "23:20:50.123456789" | "23:20:50.123456789"
68 | "23:20:50" | "23:20:50"
69 | mkLocalT("16:39:57") | "16:39:57"
70 | mkLocalT("16:39:57.1") | "16:39:57.1"
71 | }
72 |
73 | def "datetime serialisation bad inputs"() {
74 |
75 | when:
76 | coercing.serialize(input)
77 | then:
78 | thrown(expectedValue)
79 | where:
80 | input | expectedValue
81 | "23:20:50.52Z" | CoercingSerializeException
82 | "16:39:57-08:00" | CoercingSerializeException
83 | 666 || CoercingSerializeException
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/datetime/TimeScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.datetime
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseValueException
6 | import graphql.schema.CoercingSerializeException
7 | import spock.lang.Specification
8 | import spock.lang.Unroll
9 |
10 | import static graphql.scalars.util.TestKit.mkLocalDT
11 | import static graphql.scalars.util.TestKit.mkOffsetDT
12 | import static graphql.scalars.util.TestKit.mkOffsetT
13 | import static graphql.scalars.util.TestKit.mkStringValue
14 | import static graphql.scalars.util.TestKit.mkZonedDT
15 |
16 | class TimeScalarTest extends Specification {
17 |
18 | def coercing = ExtendedScalars.Time.getCoercing()
19 |
20 | @Unroll
21 | def "datetime parseValue"() {
22 |
23 | when:
24 | def result = coercing.parseValue(input)
25 | then:
26 | result == expectedValue
27 | where:
28 | input | expectedValue
29 | "23:20:50.52Z" | mkOffsetT("23:20:50.52Z")
30 | "16:39:57-08:00" | mkOffsetT("16:39:57-08:00")
31 | "12:00:27.87+00:20" | mkOffsetT("12:00:27.87+00:20")
32 | mkOffsetDT(year: 1980, hour: 3) | mkOffsetT("03:10:09+10:00")
33 | mkZonedDT(year: 1980, hour: 3) | mkOffsetT("03:10:09+10:00")
34 | }
35 |
36 | @Unroll
37 | def "datetime parseValue bad inputs"() {
38 |
39 | when:
40 | coercing.parseValue(input)
41 | then:
42 | thrown(expectedValue)
43 | where:
44 | input | expectedValue
45 | "1985-04-12" | CoercingParseValueException
46 | mkLocalDT(year: 1980, hour: 3) | CoercingParseValueException
47 | 666 || CoercingParseValueException
48 | }
49 |
50 | def "datetime AST literal"() {
51 |
52 | when:
53 | def result = coercing.parseLiteral(input)
54 | then:
55 | result == expectedValue
56 | where:
57 | input | expectedValue
58 | new StringValue("23:20:50.52Z") | mkOffsetT("23:20:50.52Z")
59 | }
60 |
61 | def "datetime serialisation"() {
62 |
63 | when:
64 | def result = coercing.serialize(input)
65 | then:
66 | result == expectedValue
67 | where:
68 | input | expectedValue
69 | "23:20:50.52Z" | "23:20:50.52Z"
70 | "16:39:57-08:00" | "16:39:57-08:00"
71 | "12:00:27.87+00:20" | "12:00:27.87+00:20"
72 | mkOffsetDT(year: 1980, hour: 3) | "03:10:09+10:00"
73 | mkZonedDT(year: 1980, hour: 3) | "03:10:09+10:00"
74 | }
75 |
76 | def "datetime valueToLiteral"() {
77 |
78 | when:
79 | def result = coercing.valueToLiteral(input)
80 | then:
81 | result.isEqualTo(expectedValue)
82 | where:
83 | input | expectedValue
84 | "23:20:50.52Z" | mkStringValue("23:20:50.52Z")
85 | "16:39:57-08:00" | mkStringValue("16:39:57-08:00")
86 | "12:00:27.87+00:20" | mkStringValue("12:00:27.87+00:20")
87 | mkOffsetDT(year: 1980, hour: 3) | mkStringValue("03:10:09+10:00")
88 | mkZonedDT(year: 1980, hour: 3) | mkStringValue("03:10:09+10:00")
89 | }
90 |
91 | def "datetime serialisation bad inputs"() {
92 |
93 | when:
94 | coercing.serialize(input)
95 | then:
96 | thrown(expectedValue)
97 | where:
98 | input | expectedValue
99 | "1985-04-12" | CoercingSerializeException
100 | mkLocalDT(year: 1980, hour: 3) | CoercingSerializeException
101 | 666 || CoercingSerializeException
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/id/UUIDScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.id
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseLiteralException
6 | import graphql.schema.CoercingParseValueException
7 | import graphql.schema.CoercingSerializeException
8 | import spock.lang.Specification
9 | import spock.lang.Unroll
10 |
11 | import static graphql.scalars.util.TestKit.mkStringValue
12 | import static graphql.scalars.util.TestKit.mkUUIDValue
13 |
14 | class UUIDScalarTest extends Specification {
15 |
16 | def coercing = ExtendedScalars.UUID.getCoercing()
17 |
18 | @Unroll
19 | def "UUID parseValue"() {
20 |
21 | when:
22 | def result = coercing.parseValue(input)
23 | then:
24 | result == expectedValue
25 | where:
26 | input | expectedValue
27 | "43f20307-603c-4ad1-83c6-6010d224fabf" | mkUUIDValue("43f20307-603c-4ad1-83c6-6010d224fabf")
28 | "787dbc2b-3ddb-4098-ad1d-63d026bac111" | mkUUIDValue("787dbc2b-3ddb-4098-ad1d-63d026bac111")
29 | }
30 |
31 | @Unroll
32 | def "UUID parseValue bad inputs"() {
33 |
34 | when:
35 | coercing.parseValue(input)
36 | then:
37 | thrown(expectedValue)
38 | where:
39 | input | expectedValue
40 | "a-string-that-is-not-uuid" | CoercingParseValueException
41 | 100 | CoercingParseValueException
42 | "1985-04-12" | CoercingParseValueException
43 | }
44 |
45 | def "UUID AST literal"() {
46 |
47 | when:
48 | def result = coercing.parseLiteral(input)
49 | then:
50 | result == expectedValue
51 | where:
52 | input | expectedValue
53 | new StringValue("6972117d-3963-4214-ab2c-fa973d7e996b") | mkUUIDValue("6972117d-3963-4214-ab2c-fa973d7e996b")
54 | }
55 |
56 | def "UUID AST literal bad inputs"() {
57 |
58 | when:
59 | coercing.parseLiteral(input)
60 | then:
61 | thrown(expectedValue)
62 | where:
63 | input | expectedValue
64 | new StringValue("a-string-that-us-not-uuid") | CoercingParseLiteralException
65 | }
66 |
67 | def "UUID serialization"() {
68 |
69 | when:
70 | def result = coercing.serialize(input)
71 | then:
72 | result == expectedValue
73 | where:
74 | input | expectedValue
75 | "42287d47-c5bd-45e4-b470-53e426d3d503" | "42287d47-c5bd-45e4-b470-53e426d3d503"
76 | "423df0f3-cf05-4eb5-b708-ae2f4b4a052d" | "423df0f3-cf05-4eb5-b708-ae2f4b4a052d"
77 | mkUUIDValue("6a90b1e6-20f3-43e5-a7ba-34db8010c071") | "6a90b1e6-20f3-43e5-a7ba-34db8010c071"
78 | }
79 |
80 | def "UUID serialization bad inputs"() {
81 |
82 | when:
83 | coercing.serialize(input)
84 | then:
85 | thrown(expectedValue)
86 | where:
87 | input | expectedValue
88 | "1985-04-12" | CoercingSerializeException
89 | 100 | CoercingSerializeException
90 | }
91 |
92 | @Unroll
93 | def "UUID valueToLiteral"() {
94 |
95 | when:
96 | def result = coercing.valueToLiteral(input)
97 | then:
98 | result.isEqualTo(expectedValue)
99 | where:
100 | input | expectedValue
101 | "42287d47-c5bd-45e4-b470-53e426d3d503" | mkStringValue("42287d47-c5bd-45e4-b470-53e426d3d503")
102 | "423df0f3-cf05-4eb5-b708-ae2f4b4a052d" | mkStringValue("423df0f3-cf05-4eb5-b708-ae2f4b4a052d")
103 | mkUUIDValue("6a90b1e6-20f3-43e5-a7ba-34db8010c071") | mkStringValue("6a90b1e6-20f3-43e5-a7ba-34db8010c071")
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/java/ScalarsBigDecimalTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.java
2 |
3 | import graphql.language.BooleanValue
4 | import graphql.language.FloatValue
5 | import graphql.language.IntValue
6 | import graphql.language.StringValue
7 | import graphql.scalars.ExtendedScalars
8 | import graphql.schema.CoercingParseLiteralException
9 | import graphql.schema.CoercingParseValueException
10 | import graphql.schema.CoercingSerializeException
11 | import spock.lang.Specification
12 | import spock.lang.Unroll
13 |
14 | import java.util.concurrent.atomic.AtomicInteger
15 |
16 | class ScalarsBigDecimalTest extends Specification {
17 |
18 | @Unroll
19 | def "BigDecimal parse literal #literal.value as #result"() {
20 | expect:
21 | ExtendedScalars.GraphQLBigDecimal.getCoercing().parseLiteral(literal) == result
22 |
23 | where:
24 | literal | result
25 | new IntValue(12345678910 as BigInteger) | new BigDecimal("12345678910")
26 | new StringValue("12345678911.12") | new BigDecimal("12345678911.12")
27 | new FloatValue(new BigDecimal("42.42")) | new BigDecimal("42.42")
28 |
29 | }
30 |
31 | @Unroll
32 | def "BigDecimal returns null for invalid #literal"() {
33 | when:
34 | ExtendedScalars.GraphQLBigDecimal.getCoercing().parseLiteral(literal)
35 | then:
36 | thrown(CoercingParseLiteralException)
37 |
38 | where:
39 | literal | _
40 | new BooleanValue(true) | _
41 | new StringValue("not a number") | _
42 | }
43 |
44 | @Unroll
45 | def "BigDecimal serialize #value into #result (#result.class)"() {
46 | expect:
47 | ExtendedScalars.GraphQLBigDecimal.getCoercing().serialize(value) == result
48 | ExtendedScalars.GraphQLBigDecimal.getCoercing().parseValue(value) == result
49 |
50 | where:
51 | value | result
52 | "42" | new BigDecimal("42")
53 | "42.123" | new BigDecimal("42.123")
54 | 42.0000d | new BigDecimal("42.000")
55 | new Integer(42) | new BigDecimal("42")
56 | "-1" | new BigDecimal("-1")
57 | new BigInteger(42) | new BigDecimal("42")
58 | new BigDecimal("42") | new BigDecimal("42")
59 | 42.3f | new BigDecimal("42.3")
60 | 42.0d | new BigDecimal("42")
61 | new Byte("42") | new BigDecimal("42")
62 | new Short("42") | new BigDecimal("42")
63 | 1234567l | new BigDecimal("1234567")
64 | new AtomicInteger(42) | new BigDecimal("42")
65 | }
66 |
67 | @Unroll
68 | def "serialize throws exception for invalid input #value"() {
69 | when:
70 | ExtendedScalars.GraphQLBigDecimal.getCoercing().serialize(value)
71 | then:
72 | thrown(CoercingSerializeException)
73 |
74 | where:
75 | value | _
76 | "" | _
77 | "not a number " | _
78 | new Object() | _
79 | }
80 |
81 | @Unroll
82 | def "parseValue throws exception for invalid input #value"() {
83 | when:
84 | ExtendedScalars.GraphQLBigDecimal.getCoercing().parseValue(value)
85 | then:
86 | thrown(CoercingParseValueException)
87 |
88 | where:
89 | value | _
90 | "" | _
91 | "not a number " | _
92 | new Object() | _
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/java/ScalarsBigIntegerTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.java
2 |
3 | import graphql.Scalars
4 | import graphql.language.BooleanValue
5 | import graphql.language.FloatValue
6 | import graphql.language.IntValue
7 | import graphql.language.StringValue
8 | import graphql.scalars.ExtendedScalars
9 | import graphql.schema.CoercingParseLiteralException
10 | import graphql.schema.CoercingParseValueException
11 | import graphql.schema.CoercingSerializeException
12 | import spock.lang.Specification
13 | import spock.lang.Unroll
14 |
15 | import java.util.concurrent.atomic.AtomicInteger
16 |
17 | class ScalarsBigIntegerTest extends Specification {
18 |
19 | @Unroll
20 | def "BigInteger parse literal #literal.value as #result"() {
21 | expect:
22 | ExtendedScalars.GraphQLBigInteger.getCoercing().parseLiteral(literal) == result
23 |
24 | where:
25 | literal | result
26 | new IntValue(12345678910 as BigInteger) | new BigInteger("12345678910")
27 | new StringValue("12345678911") | new BigInteger("12345678911")
28 | new FloatValue(new BigDecimal("42")) | new BigInteger("42")
29 | }
30 |
31 | @Unroll
32 | def "BigInteger returns null for invalid #literal"() {
33 | when:
34 | ExtendedScalars.GraphQLBigInteger.getCoercing().parseLiteral(literal)
35 | then:
36 | thrown(CoercingParseLiteralException)
37 |
38 | where:
39 | literal | _
40 | new BooleanValue(true) | _
41 | new StringValue("42.3") | _
42 | new FloatValue(new BigDecimal("12.12")) | _
43 | new StringValue("not a number") | _
44 | }
45 |
46 | @Unroll
47 | def "BigInteger serialize #value into #result (#result.class)"() {
48 | expect:
49 | ExtendedScalars.GraphQLBigInteger.getCoercing().serialize(value) == result
50 | ExtendedScalars.GraphQLBigInteger.getCoercing().parseValue(value) == result
51 |
52 | where:
53 | value | result
54 | "42" | new BigInteger("42")
55 | new Integer(42) | new BigInteger("42")
56 | "-1" | new BigInteger("-1")
57 | new BigInteger("42") | new BigInteger("42")
58 | 42.0d | new BigInteger("42")
59 | new Byte("42") | new BigInteger("42")
60 | new Short("42") | new BigInteger("42")
61 | 1234567l | new BigInteger("1234567")
62 | new AtomicInteger(42) | new BigInteger("42")
63 | }
64 |
65 | @Unroll
66 | def "serialize throws exception for invalid input #value"() {
67 | when:
68 | ExtendedScalars.GraphQLBigInteger.getCoercing().serialize(value)
69 | then:
70 | thrown(CoercingSerializeException)
71 |
72 | where:
73 | value | _
74 | "" | _
75 | "not a number " | _
76 | new BigDecimal("12.12") | _
77 | "12.12" | _
78 | new Object() | _
79 | }
80 |
81 | @Unroll
82 | def "parseValue throws exception for invalid input #value"() {
83 | when:
84 | ExtendedScalars.GraphQLBigInteger.getCoercing().parseValue(value)
85 | then:
86 | thrown(CoercingParseValueException)
87 |
88 | where:
89 | value | _
90 | "" | _
91 | "not a number " | _
92 | new BigDecimal("12.12") | _
93 | "12.12" | _
94 | new Object() | _
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/java/ScalarsByteTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.java
2 |
3 | import graphql.scalars.ExtendedScalars
4 | import graphql.language.FloatValue
5 | import graphql.language.IntValue
6 | import graphql.language.StringValue
7 | import graphql.schema.CoercingParseLiteralException
8 | import graphql.schema.CoercingParseValueException
9 | import graphql.schema.CoercingSerializeException
10 | import spock.lang.Specification
11 | import spock.lang.Unroll
12 |
13 | import java.util.concurrent.atomic.AtomicInteger
14 |
15 | class ScalarsByteTest extends Specification {
16 |
17 | @Unroll
18 | def "Byte parse literal #literal.value as #result"() {
19 | expect:
20 | ExtendedScalars.GraphQLByte.getCoercing().parseLiteral(literal) == result
21 |
22 | where:
23 | literal | result
24 | new IntValue(42 as BigInteger) | 42
25 | new IntValue(Byte.MAX_VALUE as BigInteger) | Byte.MAX_VALUE
26 | new IntValue(Byte.MIN_VALUE as BigInteger) | Byte.MIN_VALUE
27 |
28 | }
29 |
30 | @Unroll
31 | def "Byte returns null for invalid #literal"() {
32 | when:
33 | ExtendedScalars.GraphQLByte.getCoercing().parseLiteral(literal)
34 | then:
35 | thrown(CoercingParseLiteralException)
36 |
37 | where:
38 | literal | _
39 | new IntValue(12345678910 as BigInteger) | _
40 | new StringValue("-1") | _
41 | new FloatValue(42.3) | _
42 | new IntValue(Byte.MAX_VALUE + 1l as BigInteger) | _
43 | new IntValue(Byte.MIN_VALUE - 1l as BigInteger) | _
44 | new StringValue("-1") | _
45 | new FloatValue(42.3) | _
46 |
47 | }
48 |
49 | @Unroll
50 | def "Byte serialize #value into #result (#result.class)"() {
51 | expect:
52 | ExtendedScalars.GraphQLByte.getCoercing().serialize(value) == result
53 | ExtendedScalars.GraphQLByte.getCoercing().parseValue(value) == result
54 |
55 | where:
56 | value | result
57 | "42" | 42
58 | "42.0000" | 42
59 | 42.0000d | 42
60 | new Integer(42) | 42
61 | "-1" | -1
62 | new BigInteger(42) | 42
63 | new BigDecimal("42") | 42
64 | 42.0f | 42
65 | 42.0d | 42
66 | new Byte("42") | 42
67 | new Short("42") | 42
68 | 123l | 123
69 | new AtomicInteger(42) | 42
70 | Byte.MAX_VALUE | Byte.MAX_VALUE
71 | Byte.MIN_VALUE | Byte.MIN_VALUE
72 | }
73 |
74 | @Unroll
75 | def "serialize throws exception for invalid input #value"() {
76 | when:
77 | ExtendedScalars.GraphQLByte.getCoercing().serialize(value)
78 | then:
79 | thrown(CoercingSerializeException)
80 |
81 | where:
82 | value | _
83 | "" | _
84 | "not a number " | _
85 | "42.3" | _
86 | new Long(42345784398534785l) | _
87 | new Double(42.3) | _
88 | new Float(42.3) | _
89 | Byte.MAX_VALUE + 1l | _
90 | Byte.MIN_VALUE - 1l | _
91 | new Object() | _
92 |
93 | }
94 |
95 | @Unroll
96 | def "parseValue throws exception for invalid input #value"() {
97 | when:
98 | ExtendedScalars.GraphQLByte.getCoercing().parseValue(value)
99 | then:
100 | thrown(CoercingParseValueException)
101 |
102 | where:
103 | value | _
104 | "" | _
105 | "not a number " | _
106 | "42.3" | _
107 | new Long(42345784398534785l) | _
108 | new Double(42.3) | _
109 | new Float(42.3) | _
110 | Byte.MAX_VALUE + 1l | _
111 | Byte.MIN_VALUE - 1l | _
112 | new Object() | _
113 |
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/java/ScalarsCharTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.java
2 |
3 | import graphql.scalars.ExtendedScalars
4 | import graphql.language.IntValue
5 | import graphql.language.StringValue
6 | import graphql.schema.CoercingParseLiteralException
7 | import graphql.schema.CoercingParseValueException
8 | import graphql.schema.CoercingSerializeException
9 | import spock.lang.Specification
10 | import spock.lang.Unroll
11 |
12 | class ScalarsCharTest extends Specification {
13 |
14 | @Unroll
15 | def "Char parse literal #literal.value as #result"() {
16 | expect:
17 | ExtendedScalars.GraphQLChar.getCoercing().parseLiteral(literal) == result
18 |
19 | where:
20 | literal | result
21 | new StringValue("a") | 'a'
22 | new StringValue("b") | 'b'
23 |
24 | }
25 |
26 | @Unroll
27 | def "Short returns null for invalid #literal"() {
28 | when:
29 | ExtendedScalars.GraphQLChar.getCoercing().parseLiteral(literal)
30 | then:
31 | thrown(CoercingParseLiteralException)
32 |
33 | where:
34 | literal | _
35 | new StringValue("aa") | _
36 | new IntValue(12 as BigInteger) | _
37 | }
38 |
39 | @Unroll
40 | def "Short serialize #value into #result (#result.class)"() {
41 | expect:
42 | ExtendedScalars.GraphQLChar.getCoercing().serialize(value) == result
43 | ExtendedScalars.GraphQLChar.getCoercing().parseValue(value) == result
44 |
45 | where:
46 | value | result
47 | "a" | 'a'
48 | 'z' | 'z'
49 | }
50 |
51 | @Unroll
52 | def "serialize throws exception for invalid input #value"() {
53 | when:
54 | ExtendedScalars.GraphQLChar.getCoercing().serialize(value)
55 | then:
56 | thrown(CoercingSerializeException)
57 |
58 | where:
59 | value | _
60 | "" | _
61 | "aa" | _
62 | new Object() | _
63 |
64 | }
65 |
66 | @Unroll
67 | def "parseValue throws exception for invalid input #value"() {
68 | when:
69 | ExtendedScalars.GraphQLChar.getCoercing().parseValue(value)
70 | then:
71 | thrown(CoercingParseValueException)
72 |
73 | where:
74 | value | _
75 | "" | _
76 | "aa" | _
77 | new Object() | _
78 |
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/java/ScalarsLongTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.java
2 |
3 | import graphql.scalars.ExtendedScalars
4 | import graphql.language.FloatValue
5 | import graphql.language.IntValue
6 | import graphql.language.StringValue
7 | import graphql.schema.CoercingParseLiteralException
8 | import graphql.schema.CoercingParseValueException
9 | import graphql.schema.CoercingSerializeException
10 | import spock.lang.Shared
11 | import spock.lang.Specification
12 | import spock.lang.Unroll
13 |
14 | import java.util.concurrent.atomic.AtomicInteger
15 |
16 | class ScalarsLongTest extends Specification {
17 |
18 | @Shared
19 | def tooBig = new BigInteger(Long.toString(Long.MAX_VALUE)).add(new BigInteger("1"))
20 | @Shared
21 | def tooSmall = new BigInteger(Long.toString(Long.MIN_VALUE)).subtract(new BigInteger("1"))
22 |
23 | @Unroll
24 | def "Long parse literal #literal.value as #result"() {
25 | expect:
26 | ExtendedScalars.GraphQLLong.getCoercing().parseLiteral(literal) == result
27 |
28 | where:
29 | literal | result
30 | new IntValue(42 as BigInteger) | 42
31 | new IntValue(Long.MAX_VALUE as BigInteger) | Long.MAX_VALUE
32 | new IntValue(Long.MIN_VALUE as BigInteger) | Long.MIN_VALUE
33 | new StringValue("12345678910") | 12345678910
34 | new StringValue("-1") | -1
35 |
36 | }
37 |
38 | @Unroll
39 | def "Long returns null for invalid #literal"() {
40 | when:
41 | ExtendedScalars.GraphQLLong.getCoercing().parseLiteral(literal)
42 | then:
43 | thrown(CoercingParseLiteralException)
44 |
45 | where:
46 | literal | _
47 | new StringValue("not a number") | _
48 | new FloatValue(42.3) | _
49 | tooBig | null
50 | tooSmall | null
51 | new FloatValue(42.3) | null
52 | }
53 |
54 | @Unroll
55 | def "Long serialize #value into #result (#result.class)"() {
56 | expect:
57 | ExtendedScalars.GraphQLLong.getCoercing().serialize(value) == result
58 | ExtendedScalars.GraphQLLong.getCoercing().parseValue(value) == result
59 |
60 | where:
61 | value | result
62 | "42" | 42
63 | "42.0000" | 42
64 | 42.0000d | 42
65 | new Integer(42) | 42
66 | "-1" | -1
67 | new BigInteger(42) | 42
68 | new BigDecimal("42") | 42
69 | 42.0f | 42
70 | 42.0d | 42
71 | new Byte("42") | 42
72 | new Short("42") | 42
73 | 12345678910l | 12345678910l
74 | new AtomicInteger(42) | 42
75 | Long.MAX_VALUE | Long.MAX_VALUE
76 | Long.MIN_VALUE | Long.MIN_VALUE
77 | new Long(42345784398534785l) | 42345784398534785l
78 | }
79 |
80 | @Unroll
81 | def "serialize throws exception for invalid input #value"() {
82 | when:
83 | ExtendedScalars.GraphQLLong.getCoercing().serialize(value)
84 | then:
85 | thrown(CoercingSerializeException)
86 |
87 | where:
88 | value | _
89 | "" | _
90 | "not a number " | _
91 | "42.3" | _
92 | new Double(42.3) | _
93 | new Float(42.3) | _
94 | tooBig | _
95 | tooSmall | _
96 | new Object() | _
97 | }
98 |
99 | @Unroll
100 | def "parseValue throws exception for invalid input #value"() {
101 | when:
102 | ExtendedScalars.GraphQLLong.getCoercing().parseValue(value)
103 | then:
104 | thrown(CoercingParseValueException)
105 |
106 | where:
107 | value | _
108 | "" | _
109 | "not a number " | _
110 | "42.3" | _
111 | new Double(42.3) | _
112 | new Float(42.3) | _
113 | tooBig | _
114 | tooSmall | _
115 | new Object() | _
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/java/ScalarsShortTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.java
2 |
3 | import graphql.language.FloatValue
4 | import graphql.language.IntValue
5 | import graphql.language.StringValue
6 | import graphql.scalars.ExtendedScalars
7 | import graphql.schema.CoercingParseLiteralException
8 | import graphql.schema.CoercingParseValueException
9 | import graphql.schema.CoercingSerializeException
10 | import spock.lang.Specification
11 | import spock.lang.Unroll
12 |
13 | import java.util.concurrent.atomic.AtomicInteger
14 |
15 | class ScalarsShortTest extends Specification {
16 |
17 | @Unroll
18 | def "Short parse literal #literal.value as #result"() {
19 | expect:
20 | ExtendedScalars.GraphQLShort.getCoercing().parseLiteral(literal) == result
21 |
22 | where:
23 | literal | result
24 | new IntValue(42 as BigInteger) | 42
25 | new IntValue(Short.MAX_VALUE as BigInteger) | Short.MAX_VALUE
26 | new IntValue(Short.MIN_VALUE as BigInteger) | Short.MIN_VALUE
27 |
28 | }
29 |
30 | @Unroll
31 | def "Short returns null for invalid #literal"() {
32 | when:
33 | ExtendedScalars.GraphQLShort.getCoercing().parseLiteral(literal)
34 | then:
35 | thrown(CoercingParseLiteralException)
36 |
37 | where:
38 | literal | _
39 | new IntValue(12345678910 as BigInteger) | _
40 | new StringValue("-1") | _
41 | new FloatValue(42.3) | _
42 | new IntValue(Short.MAX_VALUE + 1l as BigInteger) | null
43 | new IntValue(Short.MIN_VALUE - 1l as BigInteger) | null
44 | new StringValue("-1") | null
45 | new FloatValue(42.3) | null
46 | }
47 |
48 | @Unroll
49 | def "Short serialize #value into #result (#result.class)"() {
50 | expect:
51 | ExtendedScalars.GraphQLShort.getCoercing().serialize(value) == result
52 | ExtendedScalars.GraphQLShort.getCoercing().parseValue(value) == result
53 |
54 | where:
55 | value | result
56 | "42" | 42
57 | "42.0000" | 42
58 | 42.0000d | 42
59 | new Integer(42) | 42
60 | "-1" | -1
61 | new BigInteger(42) | 42
62 | new BigDecimal("42") | 42
63 | 42.0f | 42
64 | 42.0d | 42
65 | new Byte("42") | 42
66 | new Short("42") | 42
67 | 1234l | 1234
68 | new AtomicInteger(42) | 42
69 | Short.MAX_VALUE | Short.MAX_VALUE
70 | Short.MIN_VALUE | Short.MIN_VALUE
71 | }
72 |
73 | @Unroll
74 | def "serialize throws exception for invalid input #value"() {
75 | when:
76 | ExtendedScalars.GraphQLShort.getCoercing().serialize(value)
77 | then:
78 | thrown(CoercingSerializeException)
79 |
80 | where:
81 | value | _
82 | "" | _
83 | "not a number " | _
84 | "42.3" | _
85 | new Long(42345784398534785l) | _
86 | new Double(42.3) | _
87 | new Float(42.3) | _
88 | Short.MAX_VALUE + 1l | _
89 | Short.MIN_VALUE - 1l | _
90 | new Object() | _
91 |
92 | }
93 |
94 | @Unroll
95 | def "parseValue throws exception for invalid input #value"() {
96 | when:
97 | ExtendedScalars.GraphQLShort.getCoercing().parseValue(value)
98 | then:
99 | thrown(CoercingParseValueException)
100 |
101 | where:
102 | value | _
103 | "" | _
104 | "not a number " | _
105 | "42.3" | _
106 | new Long(42345784398534785l) | _
107 | new Double(42.3) | _
108 | new Float(42.3) | _
109 | Short.MAX_VALUE + 1l | _
110 | Short.MIN_VALUE - 1l | _
111 | new Object() | _
112 |
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/locale/LocaleScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.locale
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import spock.lang.Specification
6 | import spock.lang.Unroll
7 |
8 | import static graphql.scalars.util.TestKit.mkLocale
9 | import static graphql.scalars.util.TestKit.mkStringValue
10 |
11 | class LocaleScalarTest extends Specification {
12 |
13 | def coercing = ExtendedScalars.Locale.getCoercing()
14 |
15 | @Unroll
16 | def "full locale parseValue"() {
17 |
18 | when:
19 | def result = coercing.parseValue(input)
20 | then:
21 | result == expectedValue
22 | where:
23 | input | expectedValue
24 | "en" | mkLocale("en")
25 | "ro-RO" | mkLocale("ro-RO")
26 | "zh-hakka" | mkLocale("zh-hakka")
27 | mkLocale("en") | mkLocale("en")
28 | }
29 |
30 | @Unroll
31 | def "full Locale parseLiteral"() {
32 | when:
33 | def result = coercing.parseLiteral(input)
34 | then:
35 | result == expectedValue
36 | where:
37 | input | expectedValue
38 | new StringValue("ro-RO") | mkLocale("ro-RO")
39 | }
40 |
41 | @Unroll
42 | def "full Locale serialization"() {
43 | when:
44 | def result = coercing.serialize(input)
45 | then:
46 | result == expectedValue
47 | where:
48 | input | expectedValue
49 | "ro-RO" | "ro-RO"
50 | mkLocale("ro-RO") | "ro-RO"
51 | mkLocale("en") | "en"
52 | }
53 |
54 | @Unroll
55 | def "full Locale valueToLiteral"() {
56 | when:
57 | def result = coercing.valueToLiteral(input)
58 | then:
59 | result.isEqualTo(expectedValue)
60 | where:
61 | input | expectedValue
62 | "ro-RO" | mkStringValue("ro-RO")
63 | mkLocale("ro-RO") | mkStringValue("ro-RO")
64 | mkLocale("en") | mkStringValue("en")
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/numeric/NegativeFloatScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric
2 |
3 |
4 | import graphql.language.StringValue
5 | import graphql.scalars.ExtendedScalars
6 | import graphql.schema.CoercingParseLiteralException
7 | import graphql.schema.CoercingParseValueException
8 | import graphql.schema.CoercingSerializeException
9 | import spock.lang.Specification
10 | import spock.lang.Unroll
11 |
12 | import static graphql.scalars.util.TestKit.assertValueOrException
13 | import static graphql.scalars.util.TestKit.mkFloatValue
14 | import static graphql.scalars.util.TestKit.mkIntValue
15 |
16 | class NegativeFloatScalarTest extends Specification {
17 | def coercing = ExtendedScalars.NegativeFloat.getCoercing()
18 |
19 | @Unroll
20 | def "serialize"() {
21 | def result
22 | when:
23 | try {
24 | result = coercing.serialize(input)
25 | } catch (Exception e) {
26 | result = e
27 | }
28 | then:
29 | assertValueOrException(result, expectedResult)
30 | where:
31 | input || expectedResult
32 | "NaN" || CoercingSerializeException
33 | 1 || CoercingSerializeException
34 | 0 || CoercingSerializeException
35 | 66.6 || CoercingSerializeException
36 |
37 | -666 || -666
38 | -66.6 || -66.6
39 | }
40 |
41 | @Unroll
42 | def "parseValue"() {
43 | def result
44 | when:
45 | try {
46 | result = coercing.parseValue(input)
47 | } catch (Exception e) {
48 | result = e
49 | }
50 | then:
51 | assertValueOrException(result, expectedResult)
52 | where:
53 | input || expectedResult
54 | "NaN" || CoercingParseValueException
55 | 1 || CoercingParseValueException
56 | 0 || CoercingParseValueException
57 | 66.6 || CoercingParseValueException
58 |
59 | -666 || -666
60 | -66.6 || -66.6
61 | }
62 |
63 | @Unroll
64 | def "parseLiteral"() {
65 | def result
66 | when:
67 | try {
68 | result = coercing.parseLiteral(input)
69 | } catch (Exception e) {
70 | result = e
71 | }
72 | then:
73 | assertValueOrException(result, expectedResult)
74 | where:
75 | input || expectedResult
76 | new StringValue("NaN") || CoercingParseLiteralException
77 | mkIntValue(1) || CoercingParseLiteralException
78 | mkIntValue(0) || CoercingParseLiteralException
79 | mkFloatValue(66.6) || CoercingParseLiteralException
80 |
81 | mkIntValue(-666) || -666
82 | mkFloatValue(-66.6) || -66.6
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/numeric/NegativeIntScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseLiteralException
6 | import graphql.schema.CoercingParseValueException
7 | import graphql.schema.CoercingSerializeException
8 | import spock.lang.Specification
9 | import spock.lang.Unroll
10 |
11 | import static graphql.scalars.util.TestKit.assertValueOrException
12 | import static graphql.scalars.util.TestKit.mkIntValue
13 |
14 | class NegativeIntScalarTest extends Specification {
15 | def coercing = ExtendedScalars.NegativeInt.getCoercing()
16 |
17 | @Unroll
18 | def "serialize"() {
19 | def result
20 | when:
21 | try {
22 | result = coercing.serialize(input)
23 | } catch (Exception e) {
24 | result = e
25 | }
26 | then:
27 | assertValueOrException(result, expectedResult)
28 | where:
29 | input || expectedResult
30 | "NaN" || CoercingSerializeException
31 | 1 || CoercingSerializeException
32 | 0 || CoercingSerializeException
33 |
34 | -666 || -666
35 | }
36 |
37 | @Unroll
38 | def "parseValue"() {
39 | def result
40 | when:
41 | try {
42 | result = coercing.parseValue(input)
43 | } catch (Exception e) {
44 | result = e
45 | }
46 | then:
47 | assertValueOrException(result, expectedResult)
48 | where:
49 | input || expectedResult
50 | "NaN" || CoercingParseValueException
51 | 1 || CoercingParseValueException
52 | 0 || CoercingParseValueException
53 |
54 | -666 || -666
55 | }
56 |
57 | @Unroll
58 | def "parseLiteral"() {
59 | def result
60 | when:
61 | try {
62 | result = coercing.parseLiteral(input)
63 | } catch (Exception e) {
64 | result = e
65 | }
66 | then:
67 | assertValueOrException(result, expectedResult)
68 | where:
69 | input || expectedResult
70 | new StringValue("NaN") || CoercingParseLiteralException
71 | mkIntValue(1) || CoercingParseLiteralException
72 | mkIntValue(0) || CoercingParseLiteralException
73 |
74 | mkIntValue(-666) || -666
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/numeric/NonNegativeFloatScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseLiteralException
6 | import graphql.schema.CoercingParseValueException
7 | import graphql.schema.CoercingSerializeException
8 | import spock.lang.Specification
9 | import spock.lang.Unroll
10 |
11 | import static graphql.scalars.util.TestKit.assertValueOrException
12 | import static graphql.scalars.util.TestKit.mkFloatValue
13 | import static graphql.scalars.util.TestKit.mkIntValue
14 |
15 | class NonNegativeFloatScalarTest extends Specification {
16 | def coercing = ExtendedScalars.NonNegativeFloat.getCoercing()
17 |
18 | @Unroll
19 | def "serialize"() {
20 | def result
21 | when:
22 | try {
23 | result = coercing.serialize(input)
24 | } catch (Exception e) {
25 | result = e
26 | }
27 | then:
28 | assertValueOrException(result, expectedResult)
29 | where:
30 | input || expectedResult
31 | "NaN" || CoercingSerializeException
32 | -1 || CoercingSerializeException
33 | -66.6 || CoercingSerializeException
34 |
35 | 0 || 0
36 | 666 || 666
37 | 66.6 || 66.6
38 | }
39 |
40 | @Unroll
41 | def "parseValue"() {
42 | def result
43 | when:
44 | try {
45 | result = coercing.parseValue(input)
46 | } catch (Exception e) {
47 | result = e
48 | }
49 | then:
50 | assertValueOrException(result, expectedResult)
51 | where:
52 | input || expectedResult
53 | "NaN" || CoercingParseValueException
54 | -1 || CoercingParseValueException
55 | -66.6 || CoercingParseValueException
56 |
57 | 0 || 0
58 | 666 || 666
59 | 66.6 || 66.6
60 | }
61 |
62 | @Unroll
63 | def "parseLiteral"() {
64 | def result
65 | when:
66 | try {
67 | result = coercing.parseLiteral(input)
68 | } catch (Exception e) {
69 | result = e
70 | }
71 | then:
72 | assertValueOrException(result, expectedResult)
73 | where:
74 | input || expectedResult
75 | new StringValue("NaN") || CoercingParseLiteralException
76 | mkIntValue(-1) || CoercingParseLiteralException
77 | mkFloatValue(-66.6) || CoercingParseLiteralException
78 |
79 | mkIntValue(0) || 0
80 | mkIntValue(666) || 666
81 | mkFloatValue(66.6) || 66.6
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/numeric/NonNegativeIntScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseLiteralException
6 | import graphql.schema.CoercingParseValueException
7 | import graphql.schema.CoercingSerializeException
8 | import spock.lang.Specification
9 | import spock.lang.Unroll
10 |
11 | import static graphql.scalars.util.TestKit.assertValueOrException
12 | import static graphql.scalars.util.TestKit.mkIntValue
13 |
14 | class NonNegativeIntScalarTest extends Specification {
15 | def coercing = ExtendedScalars.NonNegativeInt.getCoercing()
16 |
17 | @Unroll
18 | def "serialize"() {
19 | def result
20 | when:
21 | try {
22 | result = coercing.serialize(input)
23 | } catch (Exception e) {
24 | result = e
25 | }
26 | then:
27 | assertValueOrException(result, expectedResult)
28 | where:
29 | input || expectedResult
30 | "NaN" || CoercingSerializeException
31 | -1 || CoercingSerializeException
32 |
33 | 0 || 0
34 | 666 || 666
35 | }
36 |
37 | @Unroll
38 | def "parseValue"() {
39 | def result
40 | when:
41 | try {
42 | result = coercing.parseValue(input)
43 | } catch (Exception e) {
44 | result = e
45 | }
46 | then:
47 | assertValueOrException(result, expectedResult)
48 | where:
49 | input || expectedResult
50 | "NaN" || CoercingParseValueException
51 | -1 || CoercingParseValueException
52 |
53 | 0 || 0
54 | 666 || 666
55 | }
56 |
57 | @Unroll
58 | def "parseLiteral"() {
59 | def result
60 | when:
61 | try {
62 | result = coercing.parseLiteral(input)
63 | } catch (Exception e) {
64 | result = e
65 | }
66 | then:
67 | assertValueOrException(result, expectedResult)
68 | where:
69 | input || expectedResult
70 | new StringValue("NaN") || CoercingParseLiteralException
71 | mkIntValue(-1) || CoercingParseLiteralException
72 | mkIntValue(0) || 0
73 |
74 | mkIntValue(666) || 666
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/numeric/NonPositiveFloatScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseLiteralException
6 | import graphql.schema.CoercingParseValueException
7 | import graphql.schema.CoercingSerializeException
8 | import spock.lang.Specification
9 | import spock.lang.Unroll
10 |
11 | import static graphql.scalars.util.TestKit.assertValueOrException
12 | import static graphql.scalars.util.TestKit.mkFloatValue
13 | import static graphql.scalars.util.TestKit.mkIntValue
14 |
15 | class NonPositiveFloatScalarTest extends Specification {
16 | def coercing = ExtendedScalars.NonPositiveFloat.getCoercing()
17 |
18 | @Unroll
19 | def "serialize"() {
20 | def result
21 | when:
22 | try {
23 | result = coercing.serialize(input)
24 | } catch (Exception e) {
25 | result = e
26 | }
27 | then:
28 | assertValueOrException(result, expectedResult)
29 | where:
30 | input || expectedResult
31 | "NaN" || CoercingSerializeException
32 | 1 || CoercingSerializeException
33 |
34 | 0 || 0
35 | -666 || -666
36 | -66.6 || -66.6
37 | }
38 |
39 | @Unroll
40 | def "parseValue"() {
41 | def result
42 | when:
43 | try {
44 | result = coercing.parseValue(input)
45 | } catch (Exception e) {
46 | result = e
47 | }
48 | then:
49 | assertValueOrException(result, expectedResult)
50 | where:
51 | input || expectedResult
52 | "NaN" || CoercingParseValueException
53 | 1 || CoercingParseValueException
54 |
55 | 0 || 0
56 | -666 || -666
57 | -66.6 || -66.6
58 | }
59 |
60 | @Unroll
61 | def "parseLiteral"() {
62 | def result
63 | when:
64 | try {
65 | result = coercing.parseLiteral(input)
66 | } catch (Exception e) {
67 | result = e
68 | }
69 | then:
70 | assertValueOrException(result, expectedResult)
71 | where:
72 | input || expectedResult
73 | new StringValue("NaN") || CoercingParseLiteralException
74 | mkIntValue(1) || CoercingParseLiteralException
75 | mkFloatValue(66.6) || CoercingParseLiteralException
76 |
77 | mkIntValue(0) || 0
78 | mkIntValue(-666) || -666
79 | mkFloatValue(-66.6) || -66.6
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/numeric/NonPositiveIntScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseLiteralException
6 | import graphql.schema.CoercingParseValueException
7 | import graphql.schema.CoercingSerializeException
8 | import spock.lang.Specification
9 | import spock.lang.Unroll
10 |
11 | import static graphql.scalars.util.TestKit.assertValueOrException
12 | import static graphql.scalars.util.TestKit.mkIntValue
13 |
14 | class NonPositiveIntScalarTest extends Specification {
15 | def coercing = ExtendedScalars.NonPositiveInt.getCoercing()
16 |
17 | @Unroll
18 | def "serialize"() {
19 | def result
20 | when:
21 | try {
22 | result = coercing.serialize(input)
23 | } catch (Exception e) {
24 | result = e
25 | }
26 | then:
27 | assertValueOrException(result, expectedResult)
28 | where:
29 | input || expectedResult
30 | "NaN" || CoercingSerializeException
31 | 1 || CoercingSerializeException
32 |
33 | 0 || 0
34 | -666 || -666
35 | }
36 |
37 | @Unroll
38 | def "parseValue"() {
39 | def result
40 | when:
41 | try {
42 | result = coercing.parseValue(input)
43 | } catch (Exception e) {
44 | result = e
45 | }
46 | then:
47 | assertValueOrException(result, expectedResult)
48 | where:
49 | input || expectedResult
50 | "NaN" || CoercingParseValueException
51 | 1 || CoercingParseValueException
52 |
53 | 0 || 0
54 | -666 || -666
55 | }
56 |
57 | @Unroll
58 | def "parseLiteral"() {
59 | def result
60 | when:
61 | try {
62 | result = coercing.parseLiteral(input)
63 | } catch (Exception e) {
64 | result = e
65 | }
66 | then:
67 | assertValueOrException(result, expectedResult)
68 | where:
69 | input || expectedResult
70 | new StringValue("NaN") || CoercingParseLiteralException
71 | mkIntValue(1) || CoercingParseLiteralException
72 |
73 | mkIntValue(0) || 0
74 | mkIntValue(-666) || -666
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/numeric/PositiveFloatScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseLiteralException
6 | import graphql.schema.CoercingParseValueException
7 | import graphql.schema.CoercingSerializeException
8 | import spock.lang.Specification
9 | import spock.lang.Unroll
10 |
11 | import static graphql.scalars.util.TestKit.assertValueOrException
12 | import static graphql.scalars.util.TestKit.mkFloatValue
13 | import static graphql.scalars.util.TestKit.mkIntValue
14 |
15 | class PositiveFloatScalarTest extends Specification {
16 | def coercing = ExtendedScalars.PositiveFloat.getCoercing()
17 |
18 | @Unroll
19 | def "serialize"() {
20 | def result
21 | when:
22 | try {
23 | result = coercing.serialize(input)
24 | } catch (Exception e) {
25 | result = e
26 | }
27 | then:
28 | assertValueOrException(result, expectedResult)
29 | where:
30 | input || expectedResult
31 | "NaN" || CoercingSerializeException
32 | -1 || CoercingSerializeException
33 | 0 || CoercingSerializeException
34 | -66.6 || CoercingSerializeException
35 |
36 | 666 || 666
37 | 66.6 || 66.6
38 | }
39 |
40 | @Unroll
41 | def "parseValue"() {
42 | def result
43 | when:
44 | try {
45 | result = coercing.parseValue(input)
46 | } catch (Exception e) {
47 | result = e
48 | }
49 | then:
50 | assertValueOrException(result, expectedResult)
51 | where:
52 | input || expectedResult
53 | "NaN" || CoercingParseValueException
54 | -1 || CoercingParseValueException
55 | 0 || CoercingParseValueException
56 | -66.6 || CoercingParseValueException
57 |
58 | 666 || 666
59 | 66.6 || 66.6
60 | }
61 |
62 | @Unroll
63 | def "parseLiteral"() {
64 | def result
65 | when:
66 | try {
67 | result = coercing.parseLiteral(input)
68 | } catch (Exception e) {
69 | result = e
70 | }
71 | then:
72 | assertValueOrException(result, expectedResult)
73 | where:
74 | input || expectedResult
75 | new StringValue("NaN") || CoercingParseLiteralException
76 | mkIntValue(-1) || CoercingParseLiteralException
77 | mkIntValue(0) || CoercingParseLiteralException
78 | mkFloatValue(-66.6) || CoercingParseLiteralException
79 |
80 | mkIntValue(666) || 666
81 | mkFloatValue(66.6) || 66.6
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/numeric/PositiveIntScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.numeric
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseLiteralException
6 | import graphql.schema.CoercingParseValueException
7 | import graphql.schema.CoercingSerializeException
8 | import spock.lang.Specification
9 | import spock.lang.Unroll
10 |
11 | import static graphql.scalars.util.TestKit.assertValueOrException
12 | import static graphql.scalars.util.TestKit.mkIntValue
13 |
14 | class PositiveIntScalarTest extends Specification {
15 | def coercing = ExtendedScalars.PositiveInt.getCoercing()
16 |
17 | @Unroll
18 | def "serialize"() {
19 | def result
20 | when:
21 | try {
22 | result = coercing.serialize(input)
23 | } catch (Exception e) {
24 | result = e
25 | }
26 | then:
27 | assertValueOrException(result, expectedResult)
28 | where:
29 | input || expectedResult
30 | "NaN" || CoercingSerializeException
31 | -1 || CoercingSerializeException
32 | 0 || CoercingSerializeException
33 | 666 || 666
34 | }
35 |
36 | @Unroll
37 | def "parseValue"() {
38 | def result
39 | when:
40 | try {
41 | result = coercing.parseValue(input)
42 | } catch (Exception e) {
43 | result = e
44 | }
45 | then:
46 | assertValueOrException(result, expectedResult)
47 | where:
48 | input || expectedResult
49 | "NaN" || CoercingParseValueException
50 | -1 || CoercingParseValueException
51 | 0 || CoercingParseValueException
52 | 666 || 666
53 | }
54 |
55 | @Unroll
56 | def "parseLiteral"() {
57 | def result
58 | when:
59 | try {
60 | result = coercing.parseLiteral(input)
61 | } catch (Exception e) {
62 | result = e
63 | }
64 | then:
65 | assertValueOrException(result, expectedResult)
66 | where:
67 | input || expectedResult
68 | new StringValue("NaN") || CoercingParseLiteralException
69 | mkIntValue(-1) || CoercingParseLiteralException
70 | mkIntValue(0) || CoercingParseLiteralException
71 | mkIntValue(666) || 666
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/object/ObjectScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.object
2 |
3 | import graphql.language.ArrayValue
4 | import graphql.language.BooleanValue
5 | import graphql.language.EnumValue
6 | import graphql.language.FloatValue
7 | import graphql.language.IntValue
8 | import graphql.language.NullValue
9 | import graphql.language.ObjectField
10 | import graphql.language.ObjectValue
11 | import graphql.language.StringValue
12 | import graphql.language.Value
13 | import graphql.language.VariableReference
14 | import graphql.scalars.ExtendedScalars
15 | import spock.lang.Specification
16 | import spock.lang.Unroll
17 |
18 | class ObjectScalarTest extends Specification {
19 |
20 | def variables = [
21 | "varRef1": "value1"
22 | ]
23 |
24 | def coercing = ExtendedScalars.Object.getCoercing()
25 |
26 | @Unroll
27 | def "test AST parsing"() {
28 |
29 | when:
30 | def result = coercing.parseLiteral(input, variables)
31 | then:
32 | result == expectedResult
33 | where:
34 | input | expectedResult
35 | mkStringValue("s") | "s"
36 | mkFloatValue("99.9") | new BigDecimal("99.9")
37 | mkIntValue(666) | 666
38 | mkBooleanValue(true) | true
39 | mkEnumValue("enum") | "enum"
40 | mkVarRef("varRef1") | "value1"
41 | mkArrayValue([
42 | mkStringValue("s"), mkIntValue(666)
43 | ] as List) | ["s", 666]
44 | }
45 |
46 | @Unroll
47 | def "test AST object parsing"() {
48 |
49 | when:
50 | def result = coercing.parseLiteral(input, variables)
51 | then:
52 | result == expectedResult
53 | where:
54 | input | expectedResult
55 | mkObjectValue([
56 | fld1: mkStringValue("s"),
57 | fld2: mkIntValue(99),
58 | fld3: mkObjectValue([
59 | childFld1: mkStringValue("child1"),
60 | childFl2 : mkVarRef("varRef1")
61 | ] as Map)
62 | ] as Map) | [fld1: "s", fld2: 99, fld3: [childFld1: "child1", childFl2: "value1"]]
63 |
64 | mkObjectValue([
65 | field1: mkNullValue()
66 | ] as Map) | [field1: null] // Nested NullValue inside ObjectValue
67 | }
68 |
69 | @Unroll
70 | def "test serialize is always in and out"() {
71 | when:
72 | def result = coercing.serialize(input)
73 | then:
74 | result == expectedResult
75 | where:
76 | input | expectedResult
77 | 666 | 666
78 | "same" | "same"
79 | }
80 |
81 | @Unroll
82 | def "test parseValue is always in and out"() {
83 | when:
84 | def result = coercing.parseValue(input)
85 | then:
86 | result == expectedResult
87 | where:
88 | input | expectedResult
89 | 666 | 666
90 | "same" | "same"
91 | }
92 |
93 | @Unroll
94 | def "test valueToLiteral #input"() {
95 | when:
96 | def result = coercing.valueToLiteral(input)
97 | then:
98 | result.isEqualTo(expectedResult)
99 | where:
100 | input | expectedResult
101 | "cba" | mkStringValue("cba")
102 | 666 | mkIntValue(666)
103 | 666.99 | mkFloatValue("666.99")
104 | true | mkBooleanValue(true)
105 | null | mkNullValue()
106 |
107 | [l1: [l2: [l3: "x"]]] | mkObjectValue(
108 | [l1: mkObjectValue(
109 | [l2: mkObjectValue(
110 | [l3: mkStringValue("x")]
111 | )]
112 | )]
113 | )
114 | ["x", 1, true] | mkArrayValue([
115 | mkStringValue("x"),
116 | mkIntValue(1),
117 | mkBooleanValue(true)] as List)
118 | }
119 |
120 |
121 | ObjectValue mkObjectValue(Map fields) {
122 | def list = []
123 | for (String key : fields.keySet()) {
124 | list.add(new ObjectField(key, fields.get(key)))
125 | }
126 | new ObjectValue(list)
127 | }
128 |
129 | VariableReference mkVarRef(String name) {
130 | new VariableReference(name)
131 | }
132 |
133 | ArrayValue mkArrayValue(List values) {
134 | return new ArrayValue(values)
135 | }
136 |
137 | NullValue mkNullValue() {
138 | return NullValue.newNullValue().build()
139 | }
140 |
141 | EnumValue mkEnumValue(String val) {
142 | new EnumValue(val)
143 | }
144 |
145 | BooleanValue mkBooleanValue(boolean val) {
146 | return new BooleanValue(val)
147 | }
148 |
149 | IntValue mkIntValue(int val) {
150 | new IntValue(BigInteger.valueOf(val))
151 | }
152 |
153 | FloatValue mkFloatValue(String val) {
154 | new FloatValue(new BigDecimal(val))
155 | }
156 |
157 | StringValue mkStringValue(String val) {
158 | new StringValue(val)
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/regex/RegexScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.regex
2 |
3 | import graphql.language.StringValue
4 | import graphql.scalars.ExtendedScalars
5 | import graphql.schema.CoercingParseLiteralException
6 | import graphql.schema.CoercingParseValueException
7 | import graphql.schema.CoercingSerializeException
8 | import graphql.schema.GraphQLScalarType
9 | import spock.lang.Specification
10 | import spock.lang.Unroll
11 |
12 | import java.util.regex.Pattern
13 |
14 | import static graphql.scalars.util.TestKit.mkStringValue
15 |
16 | class RegexScalarTest extends Specification {
17 |
18 | GraphQLScalarType phoneNumberScalar = ExtendedScalars.newRegexScalar("phoneNumber")
19 | .addPattern(Pattern.compile("\\([0-9]*\\)[0-9]*"))
20 | .build()
21 |
22 | @Unroll
23 | def "basic regex parseValue"() {
24 |
25 | when:
26 | def result = phoneNumberScalar.getCoercing().parseValue(input)
27 | then:
28 | result == expectedResult
29 | where:
30 | input || expectedResult
31 | "(02)998768" || "(02)998768"
32 | }
33 |
34 | @Unroll
35 | def "basic regex parseValue bad input"() {
36 | when:
37 | phoneNumberScalar.getCoercing().parseValue(input)
38 | then:
39 | thrown(expectedResult)
40 | where:
41 | input || expectedResult
42 | "(02)abc123" || CoercingParseValueException
43 | }
44 |
45 | @Unroll
46 | def "basic regex parseLiteral"() {
47 |
48 | when:
49 | def result = phoneNumberScalar.getCoercing().parseLiteral(input)
50 | then:
51 | result == expectedResult
52 | where:
53 | input || expectedResult
54 | new StringValue("(02)998768") || "(02)998768"
55 | }
56 |
57 | @Unroll
58 | def "basic regex parseLiteral bad input"() {
59 | when:
60 | phoneNumberScalar.getCoercing().parseLiteral(input)
61 | then:
62 | thrown(expectedResult)
63 | where:
64 | input || expectedResult
65 | "(02)abc123" || CoercingParseLiteralException
66 | }
67 |
68 | @Unroll
69 | def "basic regex serialize"() {
70 |
71 | when:
72 | def result = phoneNumberScalar.getCoercing().serialize(input)
73 | then:
74 | result == expectedResult
75 | where:
76 | input || expectedResult
77 | "(02)998768" || "(02)998768"
78 | }
79 |
80 | @Unroll
81 | def "basic regex valueToLiteral"() {
82 |
83 | when:
84 | def result = phoneNumberScalar.getCoercing().valueToLiteral(input)
85 | then:
86 | result.isEqualTo(expectedResult)
87 | where:
88 | input || expectedResult
89 | "(02)998768" || mkStringValue("(02)998768")
90 | }
91 |
92 | @Unroll
93 | def "basic regex serialize bad input"() {
94 | when:
95 | phoneNumberScalar.getCoercing().serialize(input)
96 | then:
97 | thrown(expectedResult)
98 | where:
99 | input || expectedResult
100 | "(02)abc123" || CoercingSerializeException
101 | }
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/url/UrlScalarTest.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.url
2 |
3 | import graphql.language.BooleanValue
4 | import graphql.language.StringValue
5 | import graphql.scalars.ExtendedScalars
6 | import graphql.schema.CoercingParseLiteralException
7 | import graphql.schema.CoercingParseValueException
8 | import graphql.schema.CoercingSerializeException
9 | import spock.lang.Specification
10 | import spock.lang.Unroll
11 |
12 | import static graphql.scalars.util.TestKit.mkStringValue
13 |
14 | class UrlScalarTest extends Specification {
15 |
16 | def coercing = ExtendedScalars.Url.getCoercing()
17 |
18 | @Unroll
19 | def "test serialize"() {
20 |
21 | when:
22 | def result = coercing.serialize(input)
23 | then:
24 | result == expectedResult
25 | where:
26 | input | expectedResult
27 | new URL("http://www.graphql-java.com/") | new URL("http://www.graphql-java.com/")
28 | new URI("http://www.graphql-java.com/") | new URL("http://www.graphql-java.com/")
29 | new File("/this/that") | new URL("file:/this/that")
30 | "http://www.graphql-java.com/" | new URL("http://www.graphql-java.com/")
31 | }
32 |
33 | @Unroll
34 | def "test valueToLiteral"() {
35 |
36 | when:
37 | def result = coercing.valueToLiteral(input)
38 | then:
39 | result.isEqualTo(expectedResult)
40 | where:
41 | input | expectedResult
42 | new URL("http://www.graphql-java.com/") | mkStringValue("http://www.graphql-java.com/")
43 | new URI("http://www.graphql-java.com/") | mkStringValue("http://www.graphql-java.com/")
44 | new File("/this/that") | mkStringValue("file:/this/that")
45 | "http://www.graphql-java.com/" | mkStringValue("http://www.graphql-java.com/")
46 | }
47 |
48 | @Unroll
49 | def "test serialize bad inputs"() {
50 | when:
51 | coercing.serialize(input)
52 | then:
53 | thrown(exceptionClas)
54 | where:
55 | input || exceptionClas
56 | 666 || CoercingSerializeException
57 | "not/a/url" || CoercingSerializeException
58 | }
59 |
60 | @Unroll
61 | def "test parseValue"() {
62 | when:
63 | def result = coercing.parseValue(input)
64 | then:
65 | result == expectedResult
66 | where:
67 | input | expectedResult
68 | new URL("http://www.graphql-java.com/") | new URL("http://www.graphql-java.com/")
69 | new URI("http://www.graphql-java.com/") | new URL("http://www.graphql-java.com/")
70 | new File("/this/that") | new URL("file:/this/that")
71 | "http://www.graphql-java.com/" | new URL("http://www.graphql-java.com/")
72 | }
73 |
74 | @Unroll
75 | def "test parseValue bad inputs"() {
76 | when:
77 | coercing.parseValue(input)
78 | then:
79 | thrown(exceptionClas)
80 | where:
81 | input || exceptionClas
82 | 666 || CoercingParseValueException
83 | "not/a/url" || CoercingParseValueException
84 | }
85 |
86 | @Unroll
87 | def "test parseLiteral"() {
88 | when:
89 | def result = coercing.parseLiteral(input)
90 | then:
91 | result == expectedResult
92 | where:
93 | input | expectedResult
94 | new StringValue("http://www.graphql-java.com/") | new URL("http://www.graphql-java.com/")
95 | }
96 |
97 | @Unroll
98 | def "test parseLiteral bad inputs"() {
99 | when:
100 | coercing.parseLiteral(input)
101 | then:
102 | thrown(exceptionClas)
103 | where:
104 | input | exceptionClas
105 | new BooleanValue(true) | CoercingParseLiteralException
106 | new StringValue("not/a/url") | CoercingParseLiteralException
107 | }
108 |
109 |
110 | }
--------------------------------------------------------------------------------
/src/test/groovy/graphql/scalars/util/TestKit.groovy:
--------------------------------------------------------------------------------
1 | package graphql.scalars.util
2 |
3 | import graphql.language.FloatValue
4 | import graphql.language.IntValue
5 | import graphql.language.StringValue
6 | import graphql.scalars.country.code.CountryCode
7 |
8 | import java.time.LocalDate
9 | import java.time.LocalDateTime
10 | import java.time.LocalTime
11 | import java.time.OffsetDateTime
12 | import java.time.OffsetTime
13 | import java.time.ZoneId
14 | import java.time.ZoneOffset
15 | import java.time.ZonedDateTime
16 |
17 | class TestKit {
18 |
19 | static Locale mkLocale(String s) {
20 | Locale.forLanguageTag(s)
21 | }
22 |
23 | static LocalDate mkLocalDate(String s) {
24 | LocalDate.parse(s)
25 | }
26 |
27 | static OffsetDateTime mkOffsetDT(String s) {
28 | OffsetDateTime.parse(s)
29 | }
30 |
31 | static OffsetTime mkOffsetT(String s) {
32 | OffsetTime.parse(s)
33 | }
34 |
35 | static LocalTime mkLocalT(String s) {
36 | LocalTime.parse(s)
37 | }
38 |
39 | static OffsetDateTime mkOffsetDT(args) {
40 | OffsetDateTime.of(args.year ?: 1969, args.month ?: 8, args.day ?: 8, args.hour ?: 11,
41 | args.min ?: 10, args.secs ?: 9, args.nanos ?: 0, ZoneOffset.ofHours(10))
42 | }
43 |
44 | static LocalDateTime mkLocalDT(args) {
45 | LocalDateTime.of(args.year ?: 1969, args.month ?: 8, args.day ?: 8, args.hour ?: 11,
46 | args.min ?: 10, args.secs ?: 9, args.nanos ?: 0)
47 | }
48 |
49 | static ZonedDateTime mkZonedDT(args) {
50 | ZonedDateTime.of(args.year ?: 1969, args.month ?: 8, args.day ?: 8, args.hour ?: 11,
51 | args.min ?: 10, args.secs ?: 9, args.nanos ?: 0, ZoneId.ofOffset("", ZoneOffset.ofHours(10)))
52 | }
53 |
54 |
55 | static assertValueOrException(result, expectedResult) {
56 | if (result instanceof Exception) {
57 | assert result.class == expectedResult, "was " + result + " but expected exception " + expectedResult
58 | } else {
59 | assert result == expectedResult, "was " + result + " but expected " + expectedResult
60 | }
61 | true
62 | }
63 |
64 |
65 | static IntValue mkIntValue(int i) {
66 | return new IntValue(new BigInteger(String.valueOf(i)))
67 | }
68 |
69 | static IntValue mkIntValue(String s) {
70 | return new IntValue(new BigInteger(String.valueOf(s)))
71 | }
72 |
73 | static FloatValue mkFloatValue(int i) {
74 | return new FloatValue(new BigDecimal(String.valueOf(i)))
75 | }
76 |
77 | static FloatValue mkFloatValue(String s) {
78 | return new FloatValue(new BigDecimal(String.valueOf(s)))
79 | }
80 |
81 | static StringValue mkStringValue(String s) {
82 | return new StringValue(s)
83 | }
84 |
85 | static FloatValue mkFloatValue(double d) {
86 | return new FloatValue(new BigDecimal(d))
87 | }
88 |
89 | static UUID mkUUIDValue(String s) {
90 | return UUID.fromString(s)
91 | }
92 |
93 | static Currency mkCurrency(String currency) {
94 | return Currency.getInstance(currency)
95 | }
96 |
97 | static CountryCode mkCountryCode(String countryCode) {
98 | return CountryCode.valueOf(countryCode)
99 | }
100 | }
101 |
--------------------------------------------------------------------------------