transpec 2.2.2 → 2.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ed03b5875402e2f2a94f50eb8ebdd856f61aa84
4
- data.tar.gz: e81942f93e064ebac963ff6d17090bbe2e0b05f8
3
+ metadata.gz: 33c531039bdc9609412069c33d3e89135b4b2f86
4
+ data.tar.gz: 8b4956401c3985d33cc37f6738141702eb9e6e86
5
5
  SHA512:
6
- metadata.gz: 26f7db5953c2390bcd8da34b50b8a7c99252a032fdf8027de238de7f186f585e41c82cb0f749588709ff754ca7dd1b7c6df641cd0dd6a7a1b3a7a062d49ed328
7
- data.tar.gz: f936d2b514378479df192efe6980d56865477ab749f1e593878f1b98b285d22d3cf26ebf8ff888e1b1107699e2b13c05e0ed94cefcbcffb54640f3eaea2d13b1
6
+ metadata.gz: af7da633d3f8f61ca7966e1b86ac732bf037e47e78e7241270daadad59582fcaec334bfd37d9426ae817618c1474afc6fe9e488b12aca349fa6ccb615c5e11eb
7
+ data.tar.gz: e796cfb5e29b16ac5a636e0400771d4398d96a302676bfc4d7c19ad152d757d880348e5367a88c7f9e4835e7f8d560d9e589c31229705df020987234500e45a6
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## Development
4
4
 
5
+ ## v2.2.3
6
+
7
+ * Handle `its(:attr) { should have(n).items }`. ([#68](https://github.com/yujinakayama/transpec/pull/68))
8
+
5
9
  ## v2.2.2
6
10
 
7
11
  * Fix error on dynamic analysis when the project have `.rspec` file containing some `--require` options and the required file contains some RSpec API.
@@ -2,13 +2,14 @@
2
2
 
3
3
  require 'transpec/syntax'
4
4
  require 'transpec/syntax/mixin/context_sensitive'
5
+ require 'transpec/syntax/mixin/examplish'
5
6
  require 'transpec/syntax/mixin/metadata'
6
7
  require 'transpec/rspec_dsl'
7
8
 
8
9
  module Transpec
9
10
  class Syntax
10
11
  class Example < Syntax
11
- include Mixin::ContextSensitive, Mixin::Metadata, RSpecDSL
12
+ include Mixin::ContextSensitive, Mixin::Examplish, Mixin::Metadata, RSpecDSL
12
13
 
13
14
  def dynamic_analysis_target?
14
15
  super && receiver_node.nil? && EXAMPLE_METHODS.include?(method_name)
@@ -23,6 +24,10 @@ module Transpec
23
24
  convert_pending_metadata_to_skip!
24
25
  end
25
26
 
27
+ def description?
28
+ !arg_node.nil?
29
+ end
30
+
26
31
  private
27
32
 
28
33
  def convert_pending_selector_to_skip!
@@ -1,13 +1,14 @@
1
1
  # coding: utf-8
2
2
 
3
3
  require 'transpec/syntax'
4
+ require 'transpec/syntax/mixin/examplish'
4
5
  require 'transpec/syntax/mixin/send'
5
6
  require 'transpec/util'
6
7
 
7
8
  module Transpec
8
9
  class Syntax
9
10
  class Its < Syntax
10
- include Mixin::Send, Util
11
+ include Mixin::Examplish, Mixin::Send, Util
11
12
 
12
13
  define_dynamic_analysis do |rewriter|
13
14
  key = :project_requires_its?
@@ -24,15 +25,20 @@ module Transpec
24
25
  end
25
26
 
26
27
  def convert_to_describe_subject_it!
27
- front, rear = build_wrapper_codes
28
-
29
- insert_before(beginning_of_line_range(block_node), front)
28
+ insert_before(beginning_of_line_range(block_node), front_code)
29
+ insert_before(expression_range, additional_indentation_for_it)
30
30
  replace(range_from_its_to_front_of_block, 'it ')
31
- insert_after(block_node.loc.expression, rear)
31
+ insert_after(block_node.loc.expression, rear_code)
32
+
33
+ increment_block_base_indentation!
32
34
 
33
35
  add_record
34
36
  end
35
37
 
38
+ def insert_blank_line_above!
39
+ insert_before(line_range(node), "\n")
40
+ end
41
+
36
42
  def attribute_expression
37
43
  @attribute_expression ||= AttributeExpression.new(attribute_node)
38
44
  end
@@ -47,27 +53,42 @@ module Transpec
47
53
  node.parent_node
48
54
  end
49
55
 
56
+ def description?
57
+ false
58
+ end
59
+
50
60
  private
51
61
 
52
- def build_wrapper_codes
53
- front = ''
54
- rear = ''
62
+ def front_code
63
+ code = ''
55
64
 
56
- front << "\n" if !previous_line_is_blank? &&
57
- previous_and_current_line_are_same_indentation_level?
65
+ if !previous_line_is_blank? && previous_and_current_line_are_same_indentation_level?
66
+ code << "\n"
67
+ end
58
68
 
59
69
  attributes.each_with_index do |attribute, index|
60
- indentation = base_indentation + ' ' * index
70
+ indentation = block_base_indentation + ' ' * index
71
+ code << indentation + "describe #{attribute.description} do\n"
72
+ code << indentation + " subject { super()#{attribute.selector} }\n"
73
+ end
74
+
75
+ code
76
+ end
61
77
 
62
- front << indentation + "describe #{attribute.description} do\n"
63
- front << indentation + " subject { super()#{attribute.selector} }\n"
78
+ def rear_code
79
+ code = ''
64
80
 
65
- rear = "\n#{indentation}end" + rear
81
+ attributes.size.downto(1) do |level|
82
+ indentation = block_base_indentation + ' ' * (level - 1)
83
+ code << "\n"
84
+ code << "#{indentation}end"
66
85
  end
67
86
 
68
- front << ' ' * attributes.size
87
+ code
88
+ end
69
89
 
70
- [front, rear]
90
+ def additional_indentation_for_it
91
+ ' ' * attributes.size
71
92
  end
72
93
 
73
94
  def previous_line_is_blank?
@@ -76,7 +97,7 @@ module Transpec
76
97
  end
77
98
 
78
99
  def previous_and_current_line_are_same_indentation_level?
79
- indentation_of_line(previous_line_source) == base_indentation
100
+ indentation_of_line(previous_line_source) == block_base_indentation
80
101
  end
81
102
 
82
103
  def previous_line_source
@@ -85,8 +106,13 @@ module Transpec
85
106
  nil
86
107
  end
87
108
 
88
- def base_indentation
89
- @base_indentation ||= indentation_of_line(node)
109
+ # TODO: This is an ad-hoc solution for nested indentation manipulations.
110
+ def block_base_indentation
111
+ block_node.metadata[:indentation] ||= indentation_of_line(node)
112
+ end
113
+
114
+ def increment_block_base_indentation!
115
+ block_node.metadata[:indentation] = block_base_indentation + ' '
90
116
  end
91
117
 
92
118
  def range_from_its_to_front_of_block
@@ -0,0 +1,73 @@
1
+ # coding: utf-8
2
+
3
+ require 'active_support/concern'
4
+ require 'transpec/syntax/mixin/send'
5
+ require 'transpec/util'
6
+
7
+ module Transpec
8
+ class Syntax
9
+ module Mixin
10
+ module BlockOwner
11
+ extend ActiveSupport::Concern
12
+
13
+ def convert_singleline_block_to_multiline!
14
+ return unless block_has_body? # TODO
15
+
16
+ has_inserted_linefeed = false
17
+
18
+ if block_beginning_line == block_body_line
19
+ replace(range_between_block_begin_and_body, "\n#{block_base_indentation} ")
20
+ has_inserted_linefeed = true
21
+ end
22
+
23
+ if block_end_line == block_body_line
24
+ replace(range_between_block_body_and_end, "\n#{block_base_indentation}")
25
+ has_inserted_linefeed = true
26
+ end
27
+
28
+ if has_inserted_linefeed
29
+ replace(block_node.loc.begin, 'do')
30
+ replace(block_node.loc.end, 'end')
31
+ end
32
+ end
33
+
34
+ def block_base_indentation
35
+ Util.indentation_of_line(block_node)
36
+ end
37
+
38
+ def block_has_body?
39
+ !block_body_node.nil?
40
+ end
41
+
42
+ def block_body_node
43
+ block_node.children[2]
44
+ end
45
+
46
+ def block_beginning_line
47
+ block_node.loc.begin.line
48
+ end
49
+
50
+ def block_body_line
51
+ block_body_node.loc.expression.line
52
+ end
53
+
54
+ def block_end_line
55
+ block_node.loc.end.line
56
+ end
57
+
58
+ def range_between_block_begin_and_body
59
+ block_node.loc.begin.end.join(block_body_node.loc.expression.begin)
60
+ end
61
+
62
+ def range_between_block_body_and_end
63
+ block_body_node.loc.expression.end.join(block_node.loc.end.begin)
64
+ end
65
+
66
+ def block_body_range
67
+ block_body_node = block_node.children[2]
68
+ block_body_node.loc.expression
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+
3
+ require 'active_support/concern'
4
+ require 'transpec/syntax/mixin/block_owner'
5
+
6
+ module Transpec
7
+ class Syntax
8
+ module Mixin
9
+ module Examplish
10
+ extend ActiveSupport::Concern
11
+ include Mixin::BlockOwner
12
+
13
+ def block_node
14
+ parent_node.block_type? ? parent_node : nil
15
+ end
16
+
17
+ def insert_description!(description)
18
+ fail 'This example already has description' if description?
19
+ insert_before(block_node.loc.begin, "'#{description}' ")
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'transpec/syntax'
4
4
  require 'transpec/syntax/mixin/should_base'
5
- require 'transpec/rspec_dsl'
5
+ require 'transpec/syntax/example'
6
6
  require 'transpec/util'
7
7
  require 'active_support/inflector/methods'
8
8
  require 'active_support/inflector/inflections'
@@ -24,6 +24,16 @@ module Transpec
24
24
  super && receiver_node.nil? && [:should, :should_not].include?(method_name)
25
25
  end
26
26
 
27
+ def conversion_target?
28
+ return false unless dynamic_analysis_target?
29
+ return true unless runtime_data.run?(send_analysis_target_node)
30
+ return false unless defined_in_rspec_source?
31
+ # #should inside of #its is dynamically defined in MemoizedHelper,
32
+ # so it cannot be differentiated from user-defined methods by the dynamic analysis in Send.
33
+ # https://github.com/rspec/rspec-core/blob/v2.14.8/lib/rspec/core/memoized_helpers.rb#L439
34
+ !example_method_defined_by_user? || in_its?
35
+ end
36
+
27
37
  def expectize!(negative_form = 'not_to')
28
38
  replacement = 'is_expected.'
29
39
  replacement << (positive? ? 'to' : negative_form)
@@ -60,9 +70,26 @@ module Transpec
60
70
  report.records << OnelinerShouldHaveRecord.new(self, have_matcher, negative_form)
61
71
  end
62
72
 
63
- def example_has_description?
64
- send_node = example_block_node.children.first
65
- send_node.children[2]
73
+ def example
74
+ return @example if instance_variable_defined?(:@example)
75
+
76
+ @example = nil
77
+
78
+ node.each_ancestor_node do |node|
79
+ next unless node.block_type?
80
+ send_node = node.children[0]
81
+
82
+ found = Syntax.all_syntaxes.find do |syntax_class|
83
+ next unless syntax_class.ancestors.include?(Mixin::Examplish)
84
+ syntax = syntax_class.new(send_node, source_rewriter, runtime_data)
85
+ next unless syntax.conversion_target?
86
+ @example = syntax
87
+ end
88
+
89
+ break if found
90
+ end
91
+
92
+ @example
66
93
  end
67
94
 
68
95
  def build_description(size)
@@ -91,53 +118,17 @@ module Transpec
91
118
  fail 'This one-liner #should does not have #have matcher!'
92
119
  end
93
120
 
94
- unless example_has_description?
95
- insert_before(example_block_node.loc.begin, "'#{generated_description}' ")
96
- end
97
-
98
- indentation = indentation_of_line(example_block_node)
99
-
100
- unless linefeed_at_beginning_of_block?
101
- replace(left_curly_and_whitespaces_range, "do\n#{indentation} ")
102
- end
103
-
104
- unless linefeed_at_end_of_block?
105
- replace(whitespaces_and_right_curly_range, "\n#{indentation}end")
106
- end
107
- end
108
-
109
- def example_block_node
110
- return @example_block_node if instance_variable_defined?(:@example_block_node)
111
-
112
- @example_block_node = node.each_ancestor_node.find do |node|
113
- next false unless node.block_type?
114
- send_node = node.children.first
115
- receiver_node, method_name, = *send_node
116
- next false if receiver_node
117
- EXAMPLE_METHODS.include?(method_name)
121
+ unless example.description?
122
+ example.insert_description!(build_description(have_matcher.size_source))
118
123
  end
119
- end
120
-
121
- def generated_description
122
- build_description(have_matcher.size_source)
123
- end
124
124
 
125
- def linefeed_at_beginning_of_block?
126
- beginning_to_body_range = example_block_node.loc.begin.join(expression_range.begin)
127
- beginning_to_body_range.source.include?("\n")
128
- end
129
-
130
- def linefeed_at_end_of_block?
131
- body_to_end_range = expression_range.end.join(example_block_node.loc.end)
132
- body_to_end_range.source.include?("\n")
133
- end
125
+ example.convert_singleline_block_to_multiline!
134
126
 
135
- def left_curly_and_whitespaces_range
136
- expand_range_to_adjacent_whitespaces(example_block_node.loc.begin, :end)
127
+ example.insert_blank_line_above! if in_its?
137
128
  end
138
129
 
139
- def whitespaces_and_right_curly_range
140
- expand_range_to_adjacent_whitespaces(example_block_node.loc.end, :begin)
130
+ def in_its?
131
+ example.is_a?(Its)
141
132
  end
142
133
 
143
134
  def add_record(negative_form_of_to)
@@ -170,9 +161,9 @@ module Transpec
170
161
  private
171
162
 
172
163
  def build_original_syntax
173
- syntax = should.example_has_description? ? "it '...' do" : 'it {'
164
+ syntax = should.example.description? ? "it '...' do" : 'it {'
174
165
  syntax << " #{should.method_name} #{have.method_name}(n).#{original_items} "
175
- syntax << (should.example_has_description? ? 'end' : '}')
166
+ syntax << (should.example.description? ? 'end' : '}')
176
167
  end
177
168
 
178
169
  def build_converted_syntax
@@ -185,7 +176,7 @@ module Transpec
185
176
  end
186
177
 
187
178
  def converted_description
188
- if should.example_has_description?
179
+ if should.example.description?
189
180
  "it '...' do"
190
181
  else
191
182
  "it '#{should.build_description('n')}' do"
@@ -1,13 +1,14 @@
1
1
  # coding: utf-8
2
2
 
3
3
  require 'transpec/syntax'
4
+ require 'transpec/syntax/mixin/block_owner'
4
5
  require 'transpec/syntax/mixin/context_sensitive'
5
6
  require 'transpec/util'
6
7
 
7
8
  module Transpec
8
9
  class Syntax
9
10
  class Pending < Syntax
10
- include Mixin::ContextSensitive, Util
11
+ include Mixin::BlockOwner, Mixin::ContextSensitive, Util
11
12
 
12
13
  def dynamic_analysis_target?
13
14
  super && receiver_node.nil? && method_name == :pending
@@ -69,22 +70,6 @@ module Transpec
69
70
  block_node_taken_by_method(node)
70
71
  end
71
72
 
72
- def block_body_node
73
- block_node.children[2]
74
- end
75
-
76
- def block_beginning_line
77
- block_node.loc.begin.line
78
- end
79
-
80
- def block_body_line
81
- block_body_node.loc.expression.line
82
- end
83
-
84
- def block_end_line
85
- block_node.loc.end.line
86
- end
87
-
88
73
  def range_between_pending_and_body
89
74
  expression_range.end.join(block_body_node.loc.expression.begin)
90
75
  end
@@ -5,7 +5,7 @@ module Transpec
5
5
  module Version
6
6
  MAJOR = 2
7
7
  MINOR = 2
8
- PATCH = 2
8
+ PATCH = 3
9
9
 
10
10
  def self.to_s
11
11
  [MAJOR, MINOR, PATCH].join('.')
@@ -79,6 +79,37 @@ module Transpec
79
79
  it 'is converted properly' do
80
80
  converted_source.should == expected_source
81
81
  end
82
+
83
+ context 'with #its' do
84
+ let(:source) do
85
+ <<-END
86
+ describe 'example' do
87
+ subject { 'foo' }
88
+ its(:chars) { should have(3).items }
89
+ end
90
+ END
91
+ end
92
+
93
+ let(:expected_source) do
94
+ <<-END
95
+ describe 'example' do
96
+ subject { 'foo' }
97
+
98
+ describe '#chars' do
99
+ subject { super().chars }
100
+
101
+ it 'has 3 items' do
102
+ expect(subject.size).to eq(3)
103
+ end
104
+ end
105
+ end
106
+ END
107
+ end
108
+
109
+ it 'is converted properly' do
110
+ converted_source.should == expected_source
111
+ end
112
+ end
82
113
  end
83
114
 
84
115
  describe 'one-liner expectation with operator matcher' do
@@ -161,6 +161,21 @@ module Transpec
161
161
  end
162
162
  end
163
163
 
164
+ context 'when rspec is run via rake task' do
165
+ before do
166
+ create_file('Rakefile', <<-END)
167
+ require 'rspec/core/rake_task'
168
+ RSpec::Core::RakeTask.new(:spec)
169
+ END
170
+ end
171
+
172
+ let(:rspec_command) { 'rake spec' }
173
+
174
+ it 'does not raise error' do
175
+ -> { dynamic_analyzer.analyze }.should_not raise_error
176
+ end
177
+ end
178
+
164
179
  context 'when there is a .rspec file containing `--require spec_helper`' do
165
180
  before do
166
181
  create_file('.rspec', '--require spec_helper')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: transpec
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.2
4
+ version: 2.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuji Nakayama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-10 00:00:00.000000000 Z
11
+ date: 2014-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -295,7 +295,9 @@ files:
295
295
  - lib/transpec/syntax/matcher_definition.rb
296
296
  - lib/transpec/syntax/method_stub.rb
297
297
  - lib/transpec/syntax/mixin/any_instance_block.rb
298
+ - lib/transpec/syntax/mixin/block_owner.rb
298
299
  - lib/transpec/syntax/mixin/context_sensitive.rb
300
+ - lib/transpec/syntax/mixin/examplish.rb
299
301
  - lib/transpec/syntax/mixin/expect_base.rb
300
302
  - lib/transpec/syntax/mixin/expectizable.rb
301
303
  - lib/transpec/syntax/mixin/matcher_owner.rb
@@ -324,8 +326,8 @@ files:
324
326
  - lib/transpec/util.rb
325
327
  - lib/transpec/version.rb
326
328
  - spec/.rubocop.yml
327
- - spec/acceptance/configuration_modification_spec.rb
328
- - spec/acceptance/conversion_spec.rb
329
+ - spec/integration/configuration_modification_spec.rb
330
+ - spec/integration/conversion_spec.rb
329
331
  - spec/spec_helper.rb
330
332
  - spec/support/cache_helper.rb
331
333
  - spec/support/file_helper.rb
@@ -408,8 +410,8 @@ specification_version: 4
408
410
  summary: The RSpec syntax converter
409
411
  test_files:
410
412
  - spec/.rubocop.yml
411
- - spec/acceptance/configuration_modification_spec.rb
412
- - spec/acceptance/conversion_spec.rb
413
+ - spec/integration/configuration_modification_spec.rb
414
+ - spec/integration/conversion_spec.rb
413
415
  - spec/spec_helper.rb
414
416
  - spec/support/cache_helper.rb
415
417
  - spec/support/file_helper.rb