Class: Transpec::Syntax::Have

Inherits:
Transpec::Syntax show all
Includes:
Mixin::Send
Defined in:
lib/transpec/syntax/have.rb

Constant Summary collapse

QUERY_METHOD_PRIORITIES =

String#count is not query method, and there’s no way to determine whether a method is query method. Method#arity and Method#parameters return same results for Array#count (0+ args) and String#count (1+ args).

So I make #size a priority over #count so that #count won’t be chosen for String (String responds to #size).

[:size, :count, :length].freeze

Instance Attribute Summary

Attributes inherited from Transpec::Syntax

#ancestor_nodes, #node, #report, #runtime_data, #source_rewriter

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Mixin::Send

#arg_node, #arg_nodes, #arg_range, included, #method_name, #parentheses_range, #range_after_arg, #range_in_between_receiver_and_selector, #range_in_between_selector_and_arg, #receiver_node, #receiver_range, #selector_range

Methods inherited from Transpec::Syntax

all_syntaxes, #expression_range, inherited, #parent_node, register_request_for_dynamic_analysis, snake_case_name, standalone_syntaxes, #static_context_inspector, target_node?

Constructor Details

#initialize(node, expectation, source_rewriter = nil, runtime_data = nil, report = nil) ⇒ Have

Returns a new instance of Have.



31
32
33
34
35
36
37
# File 'lib/transpec/syntax/have.rb', line 31

def initialize(node, expectation, source_rewriter = nil, runtime_data = nil, report = nil)
  @node = node
  @expectation = expectation
  @source_rewriter = source_rewriter
  @runtime_data = runtime_data
  @report = report || Report.new
end

Class Method Details

.standalone?Boolean

Returns:

  • (Boolean)


20
21
22
# File 'lib/transpec/syntax/have.rb', line 20

def self.standalone?
  false
end

.target_method?(have_node, items_method_name) ⇒ Boolean

Returns:

  • (Boolean)


24
25
26
27
28
29
# File 'lib/transpec/syntax/have.rb', line 24

def self.target_method?(have_node, items_method_name)
  return false unless have_node
  have_receiver_node, have_method_name, *_ = *have_node
  return false if have_receiver_node
  [:have, :have_exactly, :have_at_least, :have_at_most].include?(have_method_name)
end

Instance Method Details

#collection_accessor_is_private?Boolean

Returns:

  • (Boolean)


92
93
94
95
# File 'lib/transpec/syntax/have.rb', line 92

def collection_accessor_is_private?
  node_data = runtime_node_data(@expectation.subject_node)
  node_data && node_data[:collection_accessor_is_private?].result
end

#convert_to_standard_expectation!Object



63
64
65
66
67
# File 'lib/transpec/syntax/have.rb', line 63

def convert_to_standard_expectation!
  replace(@expectation.subject_range, replacement_subject_source)
  replace(expression_range, replacement_matcher_source(size_source))
  register_record
end

#have_method_nameObject



79
80
81
# File 'lib/transpec/syntax/have.rb', line 79

def have_method_name
  have_node.children[1]
end

#have_nodeObject



69
70
71
# File 'lib/transpec/syntax/have.rb', line 69

def have_node
  node.children.first
end

#items_nameObject



83
84
85
# File 'lib/transpec/syntax/have.rb', line 83

def items_name
  items_node.children[1]
end

#query_methodObject



97
98
99
100
101
102
103
104
# File 'lib/transpec/syntax/have.rb', line 97

def query_method
  node_data = runtime_node_data(@expectation.subject_node)
  if node_data
    (QUERY_METHOD_PRIORITIES & node_data[:available_query_methods].result).first
  else
    default_query_method
  end
end

#register_request_for_dynamic_analysis(rewriter) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/transpec/syntax/have.rb', line 39

def register_request_for_dynamic_analysis(rewriter)
  node = @expectation.subject_node

  # `expect(owner).to have(n).things` invokes private owner#things with Object#__send__
  # if the owner does not respond to any of #size, #count and #length.
  #
  # rubocop:disable LineLength
  # https://github.com/rspec/rspec-expectations/blob/v2.14.3/lib/rspec/matchers/built_in/have.rb#L48-L58
  # rubocop:enable LineLength
  key = :subject_is_owner_of_collection?
  code = "respond_to?(#{items_name.inspect}) || " +
         "(methods & #{QUERY_METHOD_PRIORITIES.inspect}).empty?"
  rewriter.register_request(node, key, code)

  key = :available_query_methods
  code = "target = #{code} ? #{items_name} : self; " +
         "target.methods & #{QUERY_METHOD_PRIORITIES.inspect}"
  rewriter.register_request(node, key, code)

  key = :collection_accessor_is_private?
  code = "private_methods.include?(#{items_name.inspect})"
  rewriter.register_request(node, key, code)
end

#size_nodeObject



73
74
75
# File 'lib/transpec/syntax/have.rb', line 73

def size_node
  have_node.children[2]
end

#subject_is_owner_of_collection?Boolean

Returns:

  • (Boolean)


87
88
89
90
# File 'lib/transpec/syntax/have.rb', line 87

def subject_is_owner_of_collection?
  node_data = runtime_node_data(@expectation.subject_node)
  node_data && node_data[:subject_is_owner_of_collection?].result
end