Skip to content

Commit

Permalink
Support conversion of any_number_of_times
Browse files Browse the repository at this point in the history
This closes #3.
  • Loading branch information
yujinakayama committed Sep 2, 2013
1 parent 1eb0b4c commit 809d884
Show file tree
Hide file tree
Showing 9 changed files with 604 additions and 157 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Master

* Support conversion of `any_number_of_times`

## v0.0.4

* Fix a bug where necessary parentheses were not added when converting operator matcher to non-operator matcher in some cases (e.g. `== (2 - 1) + (1 + 2)` was converted into `eq(2 - 1) + (1 + 2)` unintentionally)
Expand Down
10 changes: 9 additions & 1 deletion lib/transpec/rewriter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,13 @@ def process_should(should)

def process_should_receive(should_receive)
if @configuration.convert_to_expect_to_receive?
should_receive.expectize!(@configuration.negative_form_of_to)
if should_receive.any_number_of_times? && @configuration.replace_deprecated_method?
should_receive.allowize_any_number_of_times!(@configuration.negative_form_of_to)
else
should_receive.expectize!(@configuration.negative_form_of_to)
end
elsif should_receive.any_number_of_times? && @configuration.replace_deprecated_method?
should_receive.stubize_any_number_of_times!
end
end

Expand All @@ -113,6 +119,8 @@ def process_method_stub(method_stub)
elsif @configuration.replace_deprecated_method?
method_stub.replace_deprecated_method!
end

method_stub.remove_any_number_of_times! if @configuration.replace_deprecated_method?
end

def process_be_close(be_close)
Expand Down
42 changes: 42 additions & 0 deletions lib/transpec/syntax/any_number_of_timesable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# coding: utf-8

require 'transpec/syntax'

module Transpec
class Syntax
module AnyNumberOfTimesable
def any_number_of_times?
!any_number_of_times_node.nil?
end

def remove_any_number_of_times!
return unless any_number_of_times?

map = any_number_of_times_node.loc
dot_any_number_of_times_range = map.dot.join(map.selector)
remove(dot_any_number_of_times_range)
end

private

def any_number_of_times_node
each_following_chained_method_node do |chained_node|
method_name = chained_node.children[1]
return chained_node if method_name == :any_number_of_times
end
end

def each_following_chained_method_node
return to_enum(__method__) unless block_given?

@ancestor_nodes.reverse.reduce(@node) do |child_node, parent_node|
return unless [:send, :block].include?(parent_node.type)
return unless parent_node.children.first == child_node
yield parent_node, child_node
parent_node
end
nil
end
end
end
end
10 changes: 8 additions & 2 deletions lib/transpec/syntax/expectizable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@ module Expectizable
include SendNodeSyntax

def wrap_subject_in_expect!
wrap_subject_with_method!('expect')
end

private

def wrap_subject_with_method!(method)
if Util.in_parentheses?(subject_node)
insert_before(subject_range, 'expect')
insert_before(subject_range, method)
else
insert_before(subject_range, 'expect(')
insert_before(subject_range, "#{method}(")
insert_after(subject_range, ')')
end
end
Expand Down
3 changes: 2 additions & 1 deletion lib/transpec/syntax/method_stub.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

require 'transpec/syntax'
require 'transpec/syntax/any_instanceable'
require 'transpec/syntax/any_number_of_timesable'
require 'transpec/util'
require 'English'

module Transpec
class Syntax
class MethodStub < Syntax
include AnyInstanceable, Util
include AnyInstanceable, AnyNumberOfTimesable, Util

def allowize!
# There's no way of unstubbing in #allow syntax.
Expand Down
61 changes: 34 additions & 27 deletions lib/transpec/syntax/should_receive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,46 @@
require 'transpec/syntax'
require 'transpec/syntax/expectizable'
require 'transpec/syntax/any_instanceable'
require 'transpec/syntax/any_number_of_timesable'

module Transpec
class Syntax
class ShouldReceive < Syntax
include Expectizable, AnyInstanceable
include Expectizable, AnyInstanceable, AnyNumberOfTimesable

def positive?
method_name == :should_receive
end

def expectize!(negative_form = 'not_to')
convert_to_syntax!('expect', negative_form)
end

def allowize_any_number_of_times!(negative_form = 'not_to')
return unless any_number_of_times?

convert_to_syntax!('allow', negative_form)
remove_any_number_of_times!
end

def stubize_any_number_of_times!(negative_form = 'not_to')
return unless any_number_of_times?

replace(selector_range, 'stub')
remove_any_number_of_times!
end

private

def convert_to_syntax!(syntax, negative_form)
unless in_example_group_context?
fail NotInExampleGroupContextError.new(expression_range, "##{method_name}", '#expect')
fail NotInExampleGroupContextError.new(expression_range, "##{method_name}", "##{syntax}")
end

if any_instance?
wrap_class_in_expect_any_instance_of!
else
wrap_subject_in_expect!
wrap_subject_with_method!(syntax)
end

replace(selector_range, "#{positive? ? 'to' : negative_form} receive")
Expand All @@ -40,8 +61,6 @@ def correct_block_style!
end
end

private

def self.target_receiver_node?(node)
!node.nil?
end
Expand All @@ -60,7 +79,7 @@ def wrap_class_in_expect_any_instance_of!
def broken_block_nodes
@broken_block_nodes ||= [
block_node_taken_by_with_method_with_no_normal_args,
block_node_followed_by_message_expectation_method
block_node_following_message_expectation_method
].compact.uniq
end

Expand All @@ -76,20 +95,12 @@ def broken_block_nodes
# (args
# (arg :block_arg)) nil)
def block_node_taken_by_with_method_with_no_normal_args
@ancestor_nodes.reverse.reduce(@node) do |child_node, parent_node|
return nil unless [:send, :block].include?(parent_node.type)
return nil unless parent_node.children.first == child_node

if parent_node.type == :block
return nil unless child_node.children[1] == :with
return nil if child_node.children[2]
return parent_node
end

parent_node
each_following_chained_method_node do |chained_node, child_node|
next unless chained_node.type == :block
return nil unless child_node.children[1] == :with
return nil if child_node.children[2]
return chained_node
end

nil
end

# subject.should_receive(:method_name) do |block_arg|
Expand All @@ -102,15 +113,11 @@ def block_node_taken_by_with_method_with_no_normal_args
# (sym :method_name))
# (args
# (arg :block_arg)) nil) :once)
def block_node_followed_by_message_expectation_method
@ancestor_nodes.reverse.reduce(@node) do |child_node, parent_node|
return nil unless [:send, :block].include?(parent_node.type)
return nil unless parent_node.children.first == child_node
return child_node if child_node.type == :block && parent_node.type == :send
parent_node
def block_node_following_message_expectation_method
each_following_chained_method_node do |chained_node, child_node|
next unless chained_node.type == :send
return child_node if child_node.type == :block
end

nil
end
end
end
Expand Down
Loading

0 comments on commit 809d884

Please sign in to comment.