transpec 2.2.2 → 2.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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