transpec 2.3.3 → 2.3.4

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: 585693816f02d6ca49a0a8a4e0ccec79e5514b96
4
- data.tar.gz: 082314811f1021acf7036e0bccd4f88c99348f07
3
+ metadata.gz: 86662f1a0e4d74de2c72d36a51b77e8a64b28636
4
+ data.tar.gz: a6fda615ce95a0808a127d6bf9412665accc3b7d
5
5
  SHA512:
6
- metadata.gz: e7c2c4e9b46e0a3e70939acbcda80531511edab54637e75ff1e070e88490e648f36ff69a55dd86af680d0b355c67537f2e86747e392b86d3e1889bfb8e40fc54
7
- data.tar.gz: 648882d9a093d0be7abc399922f3d1deadef1af0386e0028fd25b7cfc0f7aee5c71af05e050940c3e12d7bb34e8e5013f1523d1dd06a68b6737fc3531b96a286
6
+ metadata.gz: 062e9dcef16a3c208fef5fdc439b0e9a1fec8b99eb43dd32a6afc9f2a446c2c9e45f89472728686515e194ebecf3709b505c939edf68454c65dae01f63be81d4
7
+ data.tar.gz: e153260bbd9c687c0281a37eb82b8e6b376fa2961601580186bf26074957fa2948e30f6ea3acbf9bf2cad415af33aacdc675f27b3bb678f182a466ce0c3e1789
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## Development
4
4
 
5
+ ## v2.3.4
6
+
7
+ * Detect whether RSpec configuration `config.raise_errors_for_deprecations!` which interferes with Transpec's dynamic analysis is enabled in the user's specs and abort processing if so. ([#80](https://github.com/yujinakayama/transpec/issues/80))
8
+
5
9
  ## v2.3.3
6
10
 
7
11
  * Fix failure on dynamic analysis when there's a RSpec-like method invocation in a context that undefines `Object` methods (e.g. `after` callback in [factory_girl definition context](https://github.com/thoughtbot/factory_girl/blob/v4.4.0/lib/factory_girl/definition_proxy.rb#L3-L7)). ([#66](https://github.com/yujinakayama/transpec/issues/66))
data/CONTRIBUTING.md CHANGED
@@ -4,10 +4,11 @@ If you're going to report an issue or submit a pull request, please follow these
4
4
 
5
5
  ## Reporting an Issue
6
6
 
7
- * Provide the problematic code or the project's URL.
8
- * Include the version of Ruby you're using (`ruby --version`).
9
- * Include the version of Transpec you're using (`transpec --version`).
10
- * Include complete command-line options you passed to `transpec`.
7
+ * Provide the following information:
8
+ * The problematic code or the project's URL
9
+ * The version of Ruby you're using (`ruby --version`)
10
+ * The version of Transpec you're using (`transpec --version`)
11
+ * The complete command-line options you passed to `transpec`
11
12
 
12
13
  ## Pull Requests
13
14
 
data/Guardfile CHANGED
@@ -1,17 +1,17 @@
1
- # A sample Guardfile
2
- # More info at https://github.com/guard/guard#readme
1
+
2
+ ignore %r{^\.cache/}
3
3
 
4
4
  # This group allows to skip running RuboCop if RSpec failed,
5
5
  # like Red > Green (RSpec) > Refactor (RuboCop).
6
6
  group :red_green_refactor, halt_on_fail: true do
7
- guard :rspec, all_on_start: true, cmd: 'bundle exec rspec --format Fuubar' do
7
+ guard :rspec, cmd: 'bundle exec rspec --format Fuubar' do
8
8
  watch(%r{^spec/.+_spec\.rb$})
9
9
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
10
10
  watch('spec/spec_helper.rb') { "spec" }
11
11
  watch(%r{^spec/support/.+\.rb$}) { "spec" }
12
12
  end
13
13
 
14
- guard :rubocop, cli: '--format fuubar' do
14
+ guard :rubocop, all_on_start: false, cli: '--format fuubar' do
15
15
  watch(%r{.+\.rb$})
16
16
  watch(%r{.+\.rake$})
17
17
  watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
data/README.md CHANGED
@@ -407,11 +407,14 @@ end
407
407
  * `expect` is defined on `RSpec::Matchers` module which is included by `RSpec::Core::ExampleGroup` class, so you can use `expect` only where `self` is an instance of `RSpec::Core::ExampleGroup` (i.e. in `it` blocks, `:each` hook blocks or included module methods) or other classes that explicitly include `RSpec::Matchers`.
408
408
 
409
409
  With the above example, in the context of `1.should == 1`, the `self` is an instance of `MyAwesomeTestRunner`.
410
- Transpec tracks contexts and skips conversion if the target syntax cannot be converted in a case like this.
410
+ Transpec tracks contexts and skips conversion if the syntax cannot be converted in a case like this.
411
411
 
412
412
  ### Solution
413
413
 
414
- Include or extend `RSpec::Matchers` module to make `expect` available in the context:
414
+ Include or extend any of the following module to make RSpec syntax available in the context:
415
+
416
+ * `RSpec::Matchers` for `expect(obj).to some_matcher`
417
+ * `RSpec::Mocks::ExampleMethods` for `expect/allow(obj).to receive(:message)`
415
418
 
416
419
  ```ruby
417
420
  class MyAwesomeTestRunner
data/README.md.erb CHANGED
@@ -391,11 +391,14 @@ end
391
391
  * `expect` is defined on `RSpec::Matchers` module which is included by `RSpec::Core::ExampleGroup` class, so you can use `expect` only where `self` is an instance of `RSpec::Core::ExampleGroup` (i.e. in `it` blocks, `:each` hook blocks or included module methods) or other classes that explicitly include `RSpec::Matchers`.
392
392
 
393
393
  With the above example, in the context of `1.should == 1`, the `self` is an instance of `MyAwesomeTestRunner`.
394
- Transpec tracks contexts and skips conversion if the target syntax cannot be converted in a case like this.
394
+ Transpec tracks contexts and skips conversion if the syntax cannot be converted in a case like this.
395
395
 
396
396
  ### Solution
397
397
 
398
- Include or extend `RSpec::Matchers` module to make `expect` available in the context:
398
+ Include or extend any of the following module to make RSpec syntax available in the context:
399
+
400
+ * `RSpec::Matchers` for `expect(obj).to some_matcher`
401
+ * `RSpec::Mocks::ExampleMethods` for `expect/allow(obj).to receive(:message)`
399
402
 
400
403
  ```ruby
401
404
  class MyAwesomeTestRunner
data/lib/transpec/cli.rb CHANGED
@@ -34,12 +34,8 @@ module Transpec
34
34
  return false
35
35
  end
36
36
 
37
- begin
38
- process(paths)
39
- rescue DynamicAnalyzer::AnalysisError
40
- warn_dynamic_analysis_error
41
- return false
42
- end
37
+ done = process(paths)
38
+ return false unless done
43
39
 
44
40
  display_summary
45
41
  generate_commit_message
@@ -49,10 +45,9 @@ module Transpec
49
45
  end
50
46
 
51
47
  def process(paths)
52
- runtime_data = nil
53
-
54
48
  unless config.skip_dynamic_analysis?
55
49
  runtime_data = run_dynamic_analysis(paths)
50
+ return false unless runtime_data
56
51
  end
57
52
 
58
53
  spec_suite = SpecSuite.new(paths, runtime_data)
@@ -65,6 +60,26 @@ module Transpec
65
60
  spec_suite.specs.each do |spec|
66
61
  convert_spec(spec, spec_suite)
67
62
  end
63
+
64
+ true
65
+ end
66
+
67
+ def run_dynamic_analysis(paths)
68
+ runtime_data = nil
69
+
70
+ puts 'Copying the project for dynamic analysis...'
71
+
72
+ DynamicAnalyzer.new(rspec_command: config.rspec_command) do |analyzer|
73
+ puts "Running dynamic analysis with command #{analyzer.rspec_command.inspect}..."
74
+ runtime_data = analyzer.analyze(paths)
75
+ end
76
+
77
+ puts
78
+
79
+ runtime_data
80
+ rescue DynamicAnalyzer::AnalysisError => error
81
+ warn "\n" + error.message.color(:red)
82
+ return nil
68
83
  end
69
84
 
70
85
  def convert_spec(spec, spec_suite)
@@ -96,21 +111,6 @@ module Transpec
96
111
  end
97
112
  end
98
113
 
99
- def run_dynamic_analysis(paths)
100
- runtime_data = nil
101
-
102
- puts 'Copying the project for dynamic analysis...'
103
-
104
- DynamicAnalyzer.new(rspec_command: config.rspec_command) do |analyzer|
105
- puts "Running dynamic analysis with command #{analyzer.rspec_command.inspect}..."
106
- runtime_data = analyzer.analyze(paths)
107
- end
108
-
109
- puts
110
-
111
- runtime_data
112
- end
113
-
114
114
  def display_summary
115
115
  puts
116
116
 
@@ -145,13 +145,6 @@ module Transpec
145
145
  puts "Done! Now run #{'rspec'.bright} and check if everything is green."
146
146
  end
147
147
 
148
- def warn_dynamic_analysis_error
149
- warn 'Failed running dynamic analysis. ' \
150
- 'Transpec runs your specs in a copied project directory. ' \
151
- 'If your project requires some special setup or commands to run specs, ' \
152
- 'use -c/--rspec-command option.'
153
- end
154
-
155
148
  def warn_syntax_error(error)
156
149
  warn "Syntax error at #{error.diagnostic.location}. Skipping the file.".color(:red)
157
150
  end
@@ -18,6 +18,9 @@ module Transpec
18
18
  end
19
19
 
20
20
  def initialize(data = CompatibleOpenStruct.new)
21
+ error_message = data[RUNTIME_DATA_ERROR_MESSAGE_KEY]
22
+ fail AnalysisError, error_message if error_message
23
+
21
24
  @data = data
22
25
  end
23
26
 
@@ -29,7 +32,7 @@ module Transpec
29
32
  end
30
33
 
31
34
  def run?(node)
32
- self[node]
35
+ !self[node].nil?
33
36
  end
34
37
 
35
38
  def present?(node, key)
@@ -31,16 +31,44 @@ module <%= ANALYSIS_MODULE %>
31
31
  object
32
32
  end
33
33
 
34
- at_exit do
34
+ def error_message=(message)
35
+ data[<%= RUNTIME_DATA_ERROR_MESSAGE_KEY.inspect %>] = message
36
+ end
37
+
38
+ def validate_rspec_configuration!(config)
39
+ deprecation_stream_name = config.deprecation_stream.class.name
40
+
41
+ if deprecation_stream_name.start_with?('RSpec::Core::Formatters::DeprecationFormatter')
42
+ self.error_message = 'Aborted dynamic analysis. ' \
43
+ 'Disable `RSpec.configure { |c| c.raise_errors_for_deprecations! }` ' \
44
+ "in your spec because it interferes with Transpec's dynamic analysis."
45
+ save_result
46
+ exit(1)
47
+ end
48
+ end
49
+
50
+ def save_result
35
51
  # Use JSON rather than Marshal so that:
36
52
  # * Unknown third-party class information won't be serialized.
37
53
  # (Such objects are stored as a string.)
38
54
  # * Singleton method information won't be serialized.
39
55
  # (With Marshal.load, `singleton can't be dumped (TypeError)` will be raised.)
40
56
  require 'json'
57
+
41
58
  path = File.join(@base_path, '<%= RESULT_FILE %>')
59
+
42
60
  File.open(path, 'w') do |file|
43
61
  JSON.dump(data, file)
44
62
  end
45
63
  end
64
+
65
+ at_exit do
66
+ save_result
67
+ end
68
+ end
69
+
70
+ RSpec.configure do |config|
71
+ config.before(:suite) do
72
+ Transpec.validate_rspec_configuration!(config)
73
+ end
46
74
  end
@@ -12,8 +12,9 @@ require 'English'
12
12
 
13
13
  module Transpec
14
14
  class DynamicAnalyzer
15
- ANALYSIS_MODULE = 'TranspecAnalysis'
15
+ ANALYSIS_MODULE = 'Transpec'
16
16
  ANALYSIS_METHOD = 'analyze'
17
+ RUNTIME_DATA_ERROR_MESSAGE_KEY = :error_message
17
18
  HELPER_TEMPLATE_FILE = 'transpec_analysis_helper.rb.erb'
18
19
  RESULT_FILE = 'transpec_analysis_result.json'
19
20
 
@@ -52,16 +53,14 @@ module Transpec
52
53
 
53
54
  private
54
55
 
55
- def in_copied_project
56
+ def in_copied_project(&block)
56
57
  return yield if @in_copied_project
57
58
 
58
59
  @in_copied_project = true
59
60
 
60
61
  Dir.mktmpdir do |tmpdir|
61
62
  copied_project_path = DirectoryCloner.copy_recursively(project.path, tmpdir)
62
- Dir.chdir(copied_project_path) do
63
- yield
64
- end
63
+ Dir.chdir(copied_project_path, &block)
65
64
  end
66
65
  ensure
67
66
  @in_copied_project = false
@@ -115,8 +114,12 @@ module Transpec
115
114
  File.open(RESULT_FILE) do |file|
116
115
  RuntimeData.load(file)
117
116
  end
118
- rescue
119
- raise AnalysisError
117
+ rescue Errno::ENOENT
118
+ message = 'Failed running dynamic analysis. ' \
119
+ 'Transpec runs your specs in a copied project directory. ' \
120
+ 'If your project requires some special setup or commands to run specs, ' \
121
+ 'use -c/--rspec-command option.'
122
+ raise AnalysisError, message
120
123
  end
121
124
 
122
125
  class AnalysisError < StandardError; end
@@ -3,6 +3,7 @@
3
3
  require 'transpec/syntax'
4
4
  require 'transpec/syntax/mixin/rspec_rails'
5
5
  require 'transpec/syntax/mixin/send'
6
+ require 'transpec/dynamic_analyzer'
6
7
  require 'transpec/util'
7
8
 
8
9
  module Transpec
@@ -15,8 +16,9 @@ module Transpec
15
16
  include Mixin::Send, Mixin::RSpecRails, ConfigModification
16
17
 
17
18
  define_dynamic_analysis do |rewriter|
18
- code = "TranspecAnalysis.temporary_data[:rspec_configure_run_order] ||= 0\n" \
19
- 'TranspecAnalysis.temporary_data[:rspec_configure_run_order] += 1'
19
+ run_order = "#{DynamicAnalyzer::ANALYSIS_MODULE}.temporary_data[:rspec_configure_run_order]"
20
+ code = "#{run_order} ||= 0\n" \
21
+ "#{run_order} += 1"
20
22
  rewriter.register_request(node, :run_order, code)
21
23
  end
22
24
 
@@ -5,7 +5,7 @@ module Transpec
5
5
  module Version
6
6
  MAJOR = 2
7
7
  MINOR = 3
8
- PATCH = 3
8
+ PATCH = 4
9
9
 
10
10
  def self.to_s
11
11
  [MAJOR, MINOR, PATCH].join('.')
@@ -134,7 +134,6 @@ module Transpec
134
134
 
135
135
  context "when the project's RSpec dependency is older than the required version" do
136
136
  before do
137
- Git.stub(:command_available?).and_return(false)
138
137
  cli.project.stub(:rspec_version).and_return(RSpecVersion.new('2.13.0'))
139
138
  end
140
139
 
@@ -148,19 +147,10 @@ module Transpec
148
147
 
149
148
  context 'when analysis error is raised in the dynamic analysis' do
150
149
  before do
151
- Git.stub(:command_available?).and_return(false)
152
150
  DynamicAnalyzer.any_instance.stub(:analyze).and_raise(DynamicAnalyzer::AnalysisError)
153
151
  end
154
152
 
155
153
  include_examples 'aborts processing'
156
-
157
- it 'suggests using -c/--rspec-command option' do
158
- cli.should_receive(:warn) do |message|
159
- message.should include('use -c/--rspec-command')
160
- end
161
-
162
- cli.run(args)
163
- end
164
154
  end
165
155
 
166
156
  context 'when a syntax error is raised while processing files' do
@@ -22,7 +22,7 @@ module Transpec
22
22
  # rubocop:disable LineLength
23
23
  let(:expected_source) do
24
24
  <<-'END'
25
- TranspecAnalysis.analyze((TranspecAnalysis.analyze((subject), self, "(string)_12_19", { :should_source_location => [:object, "method(:should).source_location"], :should_example_method_defined_by_user? => [:object, "owner = method(:should).owner\nowner != RSpec::Core::ExampleGroup &&\n owner.ancestors.include?(RSpec::Core::ExampleGroup)"] }).should be(foo)), self, "(string)_12_34", { :expect_available? => [:context, "self.class.ancestors.any? { |a| a.name.start_with?('RSpec::') } && respond_to?(:expect)"] })
25
+ Transpec.analyze((Transpec.analyze((subject), self, "(string)_12_19", { :should_source_location => [:object, "method(:should).source_location"], :should_example_method_defined_by_user? => [:object, "owner = method(:should).owner\nowner != RSpec::Core::ExampleGroup &&\n owner.ancestors.include?(RSpec::Core::ExampleGroup)"] }).should be(foo)), self, "(string)_12_34", { :expect_available? => [:context, "self.class.ancestors.any? { |a| a.name.start_with?('RSpec::') } && respond_to?(:expect)"] })
26
26
  END
27
27
  end
28
28
  # rubocop:enable LineLength
@@ -43,7 +43,7 @@ module Transpec
43
43
  # rubocop:disable LineLength
44
44
  let(:expected_source) do
45
45
  <<-'END'
46
- TranspecAnalysis.analyze((TranspecAnalysis.analyze((subject), self, "(string)_14_21", { :should_source_location => [:object, "method(:should).source_location"], :should_example_method_defined_by_user? => [:object, "owner = method(:should).owner\nowner != RSpec::Core::ExampleGroup &&\n owner.ancestors.include?(RSpec::Core::ExampleGroup)"] }).should), self, "(string)_14_28", { :expect_available? => [:context, "self.class.ancestors.any? { |a| a.name.start_with?('RSpec::') } && respond_to?(:expect)"], :"=~_source_location" => [:object, "method(:=~).source_location"], :"=~_example_method_defined_by_user?" => [:object, "owner = method(:=~).owner\nowner != RSpec::Core::ExampleGroup &&\n owner.ancestors.include?(RSpec::Core::ExampleGroup)"] }) =~ TranspecAnalysis.analyze((<<-HEREDOC.gsub('foo', 'bar')), self, "(string)_32_61", { :enumerable_arg? => [:object, "is_a?(Enumerable)"] })
46
+ Transpec.analyze((Transpec.analyze((subject), self, "(string)_14_21", { :should_source_location => [:object, "method(:should).source_location"], :should_example_method_defined_by_user? => [:object, "owner = method(:should).owner\nowner != RSpec::Core::ExampleGroup &&\n owner.ancestors.include?(RSpec::Core::ExampleGroup)"] }).should), self, "(string)_14_28", { :expect_available? => [:context, "self.class.ancestors.any? { |a| a.name.start_with?('RSpec::') } && respond_to?(:expect)"], :"=~_source_location" => [:object, "method(:=~).source_location"], :"=~_example_method_defined_by_user?" => [:object, "owner = method(:=~).owner\nowner != RSpec::Core::ExampleGroup &&\n owner.ancestors.include?(RSpec::Core::ExampleGroup)"] }) =~ Transpec.analyze((<<-HEREDOC.gsub('foo', 'bar')), self, "(string)_32_61", { :enumerable_arg? => [:object, "is_a?(Enumerable)"] })
47
47
  foo
48
48
  HEREDOC
49
49
  END
@@ -65,7 +65,7 @@ module Transpec
65
65
  # rubocop:disable LineLength
66
66
  let(:expected_source) do
67
67
  <<-'END'
68
- TranspecAnalysis.analyze((expect { do_something }), self, "(string)_14_20", { :expect_source_location => [:context, "method(:expect).source_location"], :expect_example_method_defined_by_user? => [:context, "owner = method(:expect).owner\nowner != RSpec::Core::ExampleGroup &&\n owner.ancestors.include?(RSpec::Core::ExampleGroup)"] }).to throw_symbol
68
+ Transpec.analyze((expect { do_something }), self, "(string)_14_20", { :expect_source_location => [:context, "method(:expect).source_location"], :expect_example_method_defined_by_user? => [:context, "owner = method(:expect).owner\nowner != RSpec::Core::ExampleGroup &&\n owner.ancestors.include?(RSpec::Core::ExampleGroup)"] }).to throw_symbol
69
69
  END
70
70
  end
71
71
  # rubocop:enable LineLength
@@ -85,7 +85,7 @@ module Transpec
85
85
  # rubocop:disable LineLength
86
86
  let(:expected_source) do
87
87
  <<-'END'
88
- TranspecAnalysis.analyze((double 'something'), self, "(string)_14_32", { :double_source_location => [:context, "method(:double).source_location"], :double_example_method_defined_by_user? => [:context, "owner = method(:double).owner\nowner != RSpec::Core::ExampleGroup &&\n owner.ancestors.include?(RSpec::Core::ExampleGroup)"] })
88
+ Transpec.analyze((double 'something'), self, "(string)_14_32", { :double_source_location => [:context, "method(:double).source_location"], :double_example_method_defined_by_user? => [:context, "owner = method(:double).owner\nowner != RSpec::Core::ExampleGroup &&\n owner.ancestors.include?(RSpec::Core::ExampleGroup)"] })
89
89
  END
90
90
  end
91
91
  # rubocop:enable LineLength
@@ -149,7 +149,8 @@ module Transpec
149
149
  let(:source) { 'exit!' }
150
150
 
151
151
  it 'raises AnalysisError' do
152
- -> { dynamic_analyzer.analyze }.should raise_error(DynamicAnalyzer::AnalysisError)
152
+ -> { dynamic_analyzer.analyze }
153
+ .should raise_error(DynamicAnalyzer::AnalysisError, /Failed running dynamic analysis/)
153
154
  end
154
155
  end
155
156
 
@@ -248,6 +249,50 @@ module Transpec
248
249
  end
249
250
  end
250
251
 
252
+ context 'when a deprecated syntax is used with `RSpec.configure { |c| c.raise_errors_for_deprecations! }`' do
253
+ include CacheHelper
254
+
255
+ around do |example|
256
+ with_cached_dir('rspec-2.99-project') do |cached|
257
+ unless cached
258
+ create_file('Gemfile', <<-END)
259
+ source 'https://rubygems.org'
260
+ gem 'rspec', '~> 2.99'
261
+ END
262
+
263
+ Project.new.with_bundler_clean_env do
264
+ `bundle install --path vendor/bundle`
265
+ end
266
+
267
+ create_file('spec/spec_helper.rb', <<-END)
268
+ RSpec.configure do |config|
269
+ config.raise_errors_for_deprecations!
270
+ end
271
+ END
272
+ end
273
+
274
+ example.run
275
+ end
276
+ end
277
+
278
+ let(:source) do
279
+ <<-END
280
+ require 'spec_helper'
281
+
282
+ describe 'example' do
283
+ it 'is deprecated syntax' do
284
+ mock('something')
285
+ end
286
+ end
287
+ END
288
+ end
289
+
290
+ it 'raises AnalysisError with a warning message about `raise_errors_for_deprecations!`' do
291
+ -> { dynamic_analyzer.analyze }
292
+ .should raise_error(DynamicAnalyzer::AnalysisError, /raise_errors_for_deprecations!/)
293
+ end
294
+ end
295
+
251
296
  runtime_data_cache = {}
252
297
 
253
298
  subject(:runtime_data) do
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.3.3
4
+ version: 2.3.4
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-07-08 00:00:00.000000000 Z
11
+ date: 2014-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser