Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion lib/tapioca/dsl/helpers/graphql_type_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,20 @@ def type_for(type, ignore_nilable_wrapper: false, prepare_method: nil)
"T.untyped"
end

prepared = false
if prepare_method
prepare_signature = Runtime::Reflection.signature_of(prepare_method)
prepare_return_type = prepare_signature&.return_type
if valid_return_type?(prepare_return_type)
parsed_type = prepare_return_type&.to_s
prepared = true
end
end

if type.list?
# A `prepare` method receives (and returns) the argument's fully coerced value, list
# wrapper included, so its return type already accounts for `type.list?` and must not be
# wrapped again.
if type.list? && !prepared
parsed_type = "T::Array[#{parsed_type}]"
end

Expand Down
33 changes: 33 additions & 0 deletions spec/tapioca/dsl/compilers/graphql_input_object_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,39 @@ def post_id; end
assert_equal(expected, rbi_for(:CreateCommentInput))
end

it "generates correct RBI for a list argument with a prepare method returning the same list type" do
add_ruby_file("create_comment_input.rb", <<~RUBY)
class CreateCommentInput < GraphQL::Schema::InputObject
extend T::Sig

class << self
extend T::Sig
sig { params(tags: T::Array[String], _context: T.untyped).returns(T::Array[String]) }
def prepare_tags(tags, _context)
tags.map(&:downcase)
end
end

argument :tags, [String], "Tags for the comment", prepare: :prepare_tags, required: true

def resolve(tags:)
# ...
end
end
RUBY

expected = <<~RBI
# typed: strong

class CreateCommentInput
sig { returns(T::Array[::String]) }
def tags; end
end
RBI

assert_equal(expected, rbi_for(:CreateCommentInput))
end

it "doesn't fail when input object is anonymous" do
add_ruby_file("create_comment_input.rb", <<~RUBY)
class CreateCommentInput < GraphQL::Schema::InputObject
Expand Down
71 changes: 71 additions & 0 deletions spec/tapioca/dsl/compilers/graphql_mutation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,77 @@ def resolve(min:, max:, other:, proc:); end
assert_equal(expected, rbi_for(:CreateComment))
end

it "generates correct RBI for a list argument with a prepare method returning the same list type" do
add_ruby_file("create_comment.rb", <<~RUBY)
class CreateComment < GraphQL::Schema::Mutation
extend T::Sig

class << self
extend T::Sig
sig { params(tags: T::Array[String], _context: T.untyped).returns(T::Array[String]) }
def prepare_tags(tags, _context)
tags.map(&:downcase)
end
end

argument :tags, [String], "Tags for the comment", prepare: :prepare_tags

def resolve(tags:)
# ...
end
end
RUBY

expected = <<~RBI
# typed: strong

class CreateComment
sig { params(tags: T::Array[::String]).returns(T.untyped) }
def resolve(tags:); end
end
RBI

assert_equal(expected, rbi_for(:CreateComment))
end

it "generates correct RBI for a list argument with a prepare method that has no valid return type" do
add_ruby_file("create_comment.rb", <<~RUBY)
class CreateComment < GraphQL::Schema::Mutation
extend T::Sig

class << self
extend T::Sig
sig { params(tags: T::Array[String], _context: T.untyped).void }
def prepare_tags_void(tags, _context)
tags.map(&:downcase)
end

def prepare_tags_untyped(tags, _context)
tags.map(&:downcase)
end
end

argument :tags, [String], "Tags for the comment", prepare: :prepare_tags_void
argument :other_tags, [String], "Other tags for the comment", prepare: :prepare_tags_untyped

def resolve(tags:, other_tags:)
# ...
end
end
RUBY

expected = <<~RBI
# typed: strong

class CreateComment
sig { params(tags: T::Array[::String], other_tags: T::Array[::String]).returns(T.untyped) }
def resolve(tags:, other_tags:); end
end
RBI

assert_equal(expected, rbi_for(:CreateComment))
end

it "generates correct RBI arguments with a prepare method on the argument class" do
add_ruby_file("create_comment.rb", <<~RUBY)
class CommentInput < GraphQL::Schema::InputObject
Expand Down
Loading