require "spec_helper" describe GraphQL::InputObjectType do let(:input_object) { DairyProductInputType } it "has a description" do assert(input_object.description) end it "has input fields" do assert(DairyProductInputType.input_fields["fatContent"]) end describe "on a type unused by the schema" do it "has input fields" do UnreachedInputType = GraphQL::InputObjectType.define do name 'UnreachedInputType' description 'An input object type not directly used in the schema.' input_field :field, types.String end assert(UnreachedInputType.input_fields['field']) end end describe "input validation" do it "Accepts anything that yields key-value pairs to #all?" do values_obj = MinimumInputObject.new({"source" => "COW", "fatContent" => 0.4}) assert DairyProductInputType.valid_input?(values_obj, PermissiveWarden) end describe "validate_input with non-enumerable input" do it "returns a valid result for MinimumInputObject" do result = DairyProductInputType.validate_input(MinimumInputObject.new({"source" => "COW", "fatContent" => 0.4}), PermissiveWarden) assert(result.valid?) end it "returns an invalid result for MinimumInvalidInputObject" do invalid_input = MinimumInputObject.new({"source" => "KOALA", "fatContent" => 0.4}) result = DairyProductInputType.validate_input(invalid_input, PermissiveWarden) assert(!result.valid?) end end describe "validate_input with null" do let(:schema) { GraphQL::Schema.from_definition(%| type Query { a: Int } input ExampleInputObject { a: String b: Int! } |) } let(:input_type) { schema.types['ExampleInputObject'] } it "returns an invalid result when value is null for non-null argument" do invalid_input = MinimumInputObject.new({"a" => "Test", "b" => nil}) result = input_type.validate_input(invalid_input, PermissiveWarden) assert(!result.valid?) end it "returns valid result when value is null for nullable argument" do invalid_input = MinimumInputObject.new({"a" => nil, "b" => 1}) result = input_type.validate_input(invalid_input, PermissiveWarden) assert(result.valid?) end end describe "validate_input with enumerable input" do describe "with good input" do let(:input) do { "source" => "COW", "fatContent" => 0.4 } end let(:result) { DairyProductInputType.validate_input(input, PermissiveWarden) } it "returns a valid result" do assert(result.valid?) end end describe "with bad enum and float" do let(:result) { DairyProductInputType.validate_input({"source" => "KOALA", "fatContent" => "bad_num"}, PermissiveWarden) } it "returns an invalid result" do assert(!result.valid?) end it "has problems with correct paths" do paths = result.problems.map { |p| p["path"] } assert(paths.include?(["source"])) assert(paths.include?(["fatContent"])) end it "has correct problem explanation" do expected = DairyAnimalEnum.validate_input("KOALA", PermissiveWarden).problems[0]["explanation"] source_problem = result.problems.detect { |p| p["path"] == ["source"] } actual = source_problem["explanation"] assert_equal(expected, actual) end end describe "with extra argument" do let(:result) { DairyProductInputType.validate_input({"source" => "COW", "fatContent" => 0.4, "isDelicious" => false}, PermissiveWarden) } it "returns an invalid result" do assert(!result.valid?) end it "has problem with correct path" do paths = result.problems.map { |p| p["path"] } assert_equal(paths, [["isDelicious"]]) end it "has correct problem explanation" do assert(result.problems[0]["explanation"].include?("Field is not defined")) end end describe "list with one invalid element" do let(:list_type) { GraphQL::ListType.new(of_type: DairyProductInputType) } let(:result) do list_type.validate_input([ { "source" => "COW", "fatContent" => 0.4 }, { "source" => "KOALA", "fatContent" => 0.4 } ], PermissiveWarden) end it "returns an invalid result" do assert(!result.valid?) end it "has one problem" do assert_equal(result.problems.length, 1) end it "has problem with correct path" do path = result.problems[0]["path"] assert_equal(path, [1, "source"]) end it "has problem with correct explanation" do expected = DairyAnimalEnum.validate_input("KOALA", PermissiveWarden).problems[0]["explanation"] actual = result.problems[0]["explanation"] assert_equal(expected, actual) end end end end describe "coerce_result" do it "omits unspecified arguments" do result = input_object.coerce_result(fatContent: 0.3) assert_equal ["fatContent"], result.keys assert_equal 0.3, result["fatContent"] end end describe "coercion of null inputs" do let(:schema) { GraphQL::Schema.from_definition(%| type Query { a: Int } input ExampleInputObject { a: String b: Int! c: String = "Default" } |) } let(:input_type) { schema.types['ExampleInputObject'] } it "null values are returned in coerced input" do input = MinimumInputObject.new({"a" => "Test", "b" => nil,"c" => "Test"}) result = input_type.coerce_input(input) assert_equal 'Test', result['a'] assert result.key?('b') assert_equal nil, result['b'] assert_equal "Test", result['c'] end it "null values are preserved when argument has a default value" do input = MinimumInputObject.new({"a" => "Test", "b" => 1, "c" => nil}) result = input_type.coerce_input(input) assert_equal 'Test', result['a'] assert_equal 1, result['b'] assert result.key?('c') assert_equal nil, result['c'] end it "omitted arguments are not returned" do input = MinimumInputObject.new({"b" => 1, "c" => "Test"}) result = input_type.coerce_input(input) assert !result.key?('a') assert_equal 1, result['b'] assert_equal 'Test', result['c'] end end describe "when sent into a query" do let(:variables) { {} } let(:result) { DummySchema.execute(query_string, variables: variables) } describe "list inputs" do let(:variables) { {"search" => [MinimumInputObject.new({"source" => "COW", "fatContent" => 0.4})]} } let(:query_string) {%| query getCheeses($search: [DairyProductInput]!){ sheep: searchDairy(product: [{source: SHEEP, fatContent: 0.1}]) { ... cheeseFields } cow: searchDairy(product: $search) { ... cheeseFields } } fragment cheeseFields on Cheese { flavor } |} it "converts items to plain values" do sheep_value = result["data"]["sheep"]["flavor"] cow_value = result["data"]["cow"]["flavor"] assert_equal("Manchego", sheep_value) assert_equal("Brie", cow_value) end end describe "scalar inputs" do let(:query_string) {%| { cheese(id: 1.4) { flavor } } |} it "converts them to the correct type" do cheese_name = result["data"]["cheese"]["flavor"] assert_equal("Brie", cheese_name) end end end end