@@ -55,7 +55,7 @@ class Thing < GraphQL::Schema::Object
55
55
end
56
56
57
57
it "validates arguments" do
58
- err = assert_raises ArgumentError do
58
+ err = assert_raises GraphQL :: Schema :: Directive :: InvalidArgumentError do
59
59
GraphQL ::Schema ::Field . from_options (
60
60
name : :something ,
61
61
type : String ,
@@ -65,9 +65,9 @@ class Thing < GraphQL::Schema::Object
65
65
)
66
66
end
67
67
68
- assert_equal "@secret.topSecret is required, but no value was given " , err . message
68
+ assert_equal "@secret.topSecret on Thing.something is invalid (nil): Expected value to not be null " , err . message
69
69
70
- err2 = assert_raises ArgumentError do
70
+ err2 = assert_raises GraphQL :: Schema :: Directive :: InvalidArgumentError do
71
71
GraphQL ::Schema ::Field . from_options (
72
72
name : :something ,
73
73
type : String ,
@@ -77,7 +77,7 @@ class Thing < GraphQL::Schema::Object
77
77
)
78
78
end
79
79
80
- assert_equal "@secret.topSecret is required, but no value was given " , err2 . message
80
+ assert_equal "@secret.topSecret on Thing.something is invalid (12.5): Could not coerce value 12.5 to Boolean " , err2 . message
81
81
end
82
82
83
83
describe 'repeatable directives' do
@@ -400,4 +400,88 @@ def numbers
400
400
enum_value = schema . get_type ( "Stuff" ) . values [ "THING" ]
401
401
assert_equal [ [ "tag" , { name : "t7" } ] , [ "tag" , { name : "t8" } ] ] , enum_value . directives . map { |dir | [ dir . graphql_name , dir . arguments . to_h ] }
402
402
end
403
+
404
+ describe "Custom validations on definition directives" do
405
+ class DirectiveValidationSchema < GraphQL ::Schema
406
+ class ValidatedDirective < GraphQL ::Schema ::Directive
407
+ locations OBJECT , FIELD
408
+ argument :f , Float , required : false , validates : { numericality : { greater_than : 0 } }
409
+ argument :s , String , required : false , validates : { format : { with : /^[a-z]{3}$/ } }
410
+ validates required : { one_of : [ :f , :s ] }
411
+ end
412
+
413
+ class Query < GraphQL ::Schema ::Object
414
+ field :i , Int , fallback_value : 100
415
+ end
416
+
417
+ query ( Query )
418
+ directive ( ValidatedDirective )
419
+ end
420
+
421
+ it "runs custom validation during execution" do
422
+ f_err_res = DirectiveValidationSchema . execute ( "{ i @validatedDirective(f: -10) }" )
423
+ assert_equal [ { "message" => "f must be greater than 0" , "locations" => [ { "line" => 1 , "column" => 5 } ] , "path" => [ "i" ] } ] , f_err_res [ "errors" ]
424
+
425
+ s_err_res = DirectiveValidationSchema . execute ( "{ i @validatedDirective(s: \" wnrn\" ) }" )
426
+ assert_equal [ { "message" => "s is invalid" , "locations" => [ { "line" => 1 , "column" => 5 } ] , "path" => [ "i" ] } ] , s_err_res [ "errors" ]
427
+
428
+ f_s_err_res = DirectiveValidationSchema . execute ( "{ i @validatedDirective }" )
429
+ assert_equal [ { "message" => "validatedDirective must include exactly one of the following arguments: f, s." , "locations" => [ { "line" => 1 , "column" => 5 } ] , "path" => [ "i" ] } ] , f_s_err_res [ "errors" ]
430
+ end
431
+
432
+ it "runs custom validation during definition" do
433
+ obj_type = Class . new ( GraphQL ::Schema ::Object )
434
+ directive_defn = DirectiveValidationSchema ::ValidatedDirective
435
+ obj_type . directive ( directive_defn , f : 1 )
436
+ f_err = assert_raises GraphQL ::Schema ::Validator ::ValidationFailedError do
437
+ obj_type . directive ( directive_defn , f : -1 )
438
+ end
439
+ assert_equal "f must be greater than 0" , f_err . message
440
+
441
+ obj_type . directive ( directive_defn , s : "abc" )
442
+ s_err = assert_raises GraphQL ::Schema ::Validator ::ValidationFailedError do
443
+ obj_type . directive ( directive_defn , s : "defg" )
444
+ end
445
+ assert_equal "s is invalid" , s_err . message
446
+
447
+ required_err = assert_raises GraphQL ::Schema ::Validator ::ValidationFailedError do
448
+ obj_type . directive ( directive_defn )
449
+ end
450
+ assert_equal "validatedDirective must include exactly one of the following arguments: f, s." , required_err . message
451
+ end
452
+ end
453
+
454
+ describe "Validating schema directives" do
455
+ def build_sdl ( size :)
456
+ <<~GRAPHQL
457
+ directive @tshirt(size: Size!) on INTERFACE | OBJECT
458
+
459
+ type MyType @tshirt(size: #{ size } ) {
460
+ color: String
461
+ }
462
+
463
+ type Query {
464
+ myType: MyType
465
+ }
466
+
467
+ enum Size {
468
+ LARGE
469
+ MEDIUM
470
+ SMALL
471
+ }
472
+ GRAPHQL
473
+ end
474
+
475
+ it "Raises a nice error for invalid enum values" do
476
+ valid_sdl = build_sdl ( size : "MEDIUM" )
477
+ assert_equal valid_sdl , GraphQL ::Schema . from_definition ( valid_sdl ) . to_definition
478
+
479
+ typo_sdl = build_sdl ( size : "BLAH" )
480
+ err = assert_raises GraphQL ::Schema ::Directive ::InvalidArgumentError do
481
+ GraphQL ::Schema . from_definition ( typo_sdl )
482
+ end
483
+ expected_msg = '@tshirt.size on MyType is invalid ("BLAH"): Expected "BLAH" to be one of: LARGE, MEDIUM, SMALL'
484
+ assert_equal expected_msg , err . message
485
+ end
486
+ end
403
487
end
0 commit comments