transpec 1.1.2 → 1.2.0

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.
@@ -29,7 +29,7 @@ module Transpec
29
29
  check_syntax_availability(__method__)
30
30
  end
31
31
 
32
- def allowize!
32
+ def allowize!(receive_messages_available = false)
33
33
  # There's no way of unstubbing in #allow syntax.
34
34
  return unless [:stub, :stub!].include?(method_name)
35
35
 
@@ -37,15 +37,19 @@ module Transpec
37
37
  fail InvalidContextError.new(selector_range, "##{method_name}", '#allow')
38
38
  end
39
39
 
40
- if arg_node.type == :hash
41
- expressions = build_allow_expressions_from_hash_node(arg_node)
42
- replace(expression_range, expressions)
43
- else
44
- expression = build_allow_expression(arg_node)
45
- replace(expression_range, expression)
46
- end
40
+ source, type = if arg_node.type == :hash
41
+ if receive_messages_available
42
+ [build_allow_to_receive_messages_expression, :allow_to_receive_messages]
43
+ else
44
+ [build_allow_expressions_from_hash_node(arg_node), :allow_to_receive]
45
+ end
46
+ else
47
+ [build_allow_expression(arg_node), :allow_to_receive]
48
+ end
47
49
 
48
- register_record(:allow)
50
+ replace(expression_range, source)
51
+
52
+ register_record(type)
49
53
  end
50
54
 
51
55
  def convert_deprecated_method!
@@ -87,6 +91,14 @@ module Transpec
87
91
  expression
88
92
  end
89
93
 
94
+ def build_allow_to_receive_messages_expression
95
+ expression = allow_source
96
+ expression << range_in_between_receiver_and_selector.source
97
+ expression << 'to receive_messages'
98
+ expression << parentheses_range.source
99
+ expression
100
+ end
101
+
90
102
  def allow_source
91
103
  if any_instance?
92
104
  class_source = class_node_of_any_instance.loc.expression.source
@@ -122,10 +134,15 @@ module Transpec
122
134
 
123
135
  def converted_syntax(conversion_type)
124
136
  case conversion_type
125
- when :allow
137
+ when :allow_to_receive, :allow_to_receive_messages
126
138
  syntax = any_instance? ? 'allow_any_instance_of(SomeClass)' : 'allow(obj)'
127
- syntax << '.to receive(:message)'
128
- syntax << '.and_return(value)' if arg_node.type == :hash
139
+ syntax << '.to '
140
+ if conversion_type == :allow_to_receive
141
+ syntax << 'receive(:message)'
142
+ syntax << '.and_return(value)' if arg_node.type == :hash
143
+ else
144
+ syntax << 'receive_messages(:message => value)'
145
+ end
129
146
  when :deprecated
130
147
  syntax = 'obj.'
131
148
  syntax << replacement_method_for_deprecated_method
@@ -4,8 +4,8 @@ module Transpec
4
4
  # http://semver.org/
5
5
  module Version
6
6
  MAJOR = 1
7
- MINOR = 1
8
- PATCH = 2
7
+ MINOR = 2
8
+ PATCH = 0
9
9
 
10
10
  def self.to_s
11
11
  [MAJOR, MINOR, PATCH].join('.')
data/lib/transpec.rb CHANGED
@@ -1,7 +1,31 @@
1
1
  # coding: utf-8
2
2
 
3
+ require 'transpec/rspec_version'
4
+
3
5
  module Transpec
4
6
  def self.root
5
7
  File.expand_path('..', File.dirname(__FILE__))
6
8
  end
9
+
10
+ def self.required_rspec_version
11
+ @required_rspec_version ||= begin
12
+ gemspec_path = File.join(root, 'transpec.gemspec')
13
+ gem_specification = Gem::Specification.load(gemspec_path)
14
+ rspec_dependency = gem_specification.dependencies.find { |d| d.name == 'rspec' }
15
+
16
+ if rspec_dependency
17
+ rspec_requirement = rspec_dependency.requirement
18
+ gem_version = rspec_requirement.requirements.first.find { |r| r.is_a?(Gem::Version) }
19
+ RSpecVersion.new(gem_version.to_s)
20
+ else
21
+ # Using development version of RSpec with Bundler.
22
+ current_rspec_version
23
+ end
24
+ end
25
+ end
26
+
27
+ def self.current_rspec_version
28
+ require 'rspec/version'
29
+ RSpecVersion.new(RSpec::Version::STRING)
30
+ end
7
31
  end
@@ -17,6 +17,17 @@ module CacheHelper
17
17
  end
18
18
  end
19
19
 
20
+ def with_cached_dir(dirname)
21
+ dir_path = File.join(cache_dir, dirname)
22
+
23
+ cached = Dir.exist?(dir_path)
24
+ FileUtils.mkdir_p(dir_path) unless cached
25
+
26
+ Dir.chdir(dir_path) do
27
+ yield cached
28
+ end
29
+ end
30
+
20
31
  def load_cache(path)
21
32
  File.open(path) do |file|
22
33
  Marshal.load(file)
@@ -36,8 +47,8 @@ module CacheHelper
36
47
 
37
48
  def cache_dir
38
49
  @cache_dir ||= begin
39
- spec_dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
40
- cache_dir = File.join(spec_dir, 'cache')
50
+ project_root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
51
+ cache_dir = File.join(project_root, 'tmp', 'spec_cache')
41
52
 
42
53
  unless Dir.exist?(cache_dir)
43
54
  require 'fileutils'
@@ -9,6 +9,10 @@ module Transpec
9
9
 
10
10
  subject(:cli) { CLI.new }
11
11
 
12
+ before do
13
+ cli.project.stub(:rspec_version).and_return(Transpec.current_rspec_version)
14
+ end
15
+
12
16
  describe '.run' do
13
17
  it 'invokes #run' do
14
18
  args = ['foo', 'bar']
@@ -52,6 +56,13 @@ module Transpec
52
56
  end
53
57
  end
54
58
 
59
+ shared_examples 'aborts processing' do
60
+ it 'aborts processing' do
61
+ cli.should_not_receive(:convert_file)
62
+ cli.run(args).should be_false
63
+ end
64
+ end
65
+
55
66
  context 'when git is available' do
56
67
  before { Git.stub(:command_available?).and_return(true) }
57
68
 
@@ -61,11 +72,8 @@ module Transpec
61
72
  context 'and the repository is not clean' do
62
73
  before { Git.stub(:clean?).and_return(false) }
63
74
 
64
- context '--force option is not specified' do
65
- it 'aborts processing' do
66
- cli.should_not_receive(:convert_file)
67
- cli.run(args).should be_false
68
- end
75
+ context 'and --force option is not specified' do
76
+ include_examples 'aborts processing'
69
77
 
70
78
  it 'warns to the user' do
71
79
  cli.should_receive(:warn) do |arg|
@@ -76,8 +84,14 @@ module Transpec
76
84
  end
77
85
  end
78
86
 
79
- context '#forced? is true' do
80
- before { args << '--force' }
87
+ context 'and --force option is specified' do
88
+ before do
89
+ args << '--force'
90
+ # Silence "fatal: Not a git repository (or any of the parent directories): .git"
91
+ # from Bundler.
92
+ `git init`
93
+ end
94
+
81
95
  include_examples 'rewrites files'
82
96
  end
83
97
  end
@@ -99,6 +113,23 @@ module Transpec
99
113
  include_examples 'rewrites files'
100
114
  end
101
115
 
116
+ context "when the project's RSpec dependency is older than the required version" do
117
+ before do
118
+ Git.stub(:command_available?).and_return(false)
119
+ cli.project.stub(:rspec_version).and_return(RSpecVersion.new('2.13.0'))
120
+ end
121
+
122
+ include_examples 'aborts processing'
123
+
124
+ it 'warns to the user' do
125
+ cli.should_receive(:warn) do |arg|
126
+ arg.should match(/rspec.+dependency/i)
127
+ end
128
+
129
+ cli.run(args)
130
+ end
131
+ end
132
+
102
133
  context 'when a syntax error is raised while processing files' do
103
134
  let(:args) { [invalid_syntax_file_path, valid_syntax_file_path] }
104
135
  let(:invalid_syntax_file_path) { 'invalid_example.rb' }
@@ -18,22 +18,19 @@ module Transpec
18
18
  [:parenthesize_matcher_arg?, true],
19
19
  [:forced?, false],
20
20
  [:skip_dynamic_analysis?, false],
21
- [:generate_commit_message?, false]
21
+ [:generate_commit_message?, false],
22
+ [:negative_form_of_to, 'not_to'],
23
+ [:boolean_matcher_type, :conditional],
24
+ [:form_of_be_falsey, 'be_falsey']
22
25
  ].each do |attribute, value|
23
26
  describe "##{attribute}" do
24
27
  subject { configuration.send(attribute) }
25
28
 
26
- it "is #{value}" do
29
+ it "is #{value.inspect}" do
27
30
  should == value
28
31
  end
29
32
  end
30
33
  end
31
-
32
- describe '#negative_form_of_to' do
33
- it 'is "not_to"' do
34
- configuration.negative_form_of_to.should == 'not_to'
35
- end
36
- end
37
34
  end
38
35
 
39
36
  describe '#negative_form_of_to=' do
@@ -54,5 +51,43 @@ module Transpec
54
51
  end
55
52
  end
56
53
  end
54
+
55
+ describe '#boolean_matcher_type=' do
56
+ [:conditional, :exact] .each do |type|
57
+ context "when #{type.inspect} is passed" do
58
+ it "sets #{type.inspect}" do
59
+ configuration.boolean_matcher_type = type
60
+ configuration.boolean_matcher_type.should == type
61
+ end
62
+ end
63
+ end
64
+
65
+ context 'when a type other than :conditional or :exact is passed' do
66
+ it 'raises error' do
67
+ lambda do
68
+ configuration.boolean_matcher_type = :foo
69
+ end.should raise_error(ArgumentError)
70
+ end
71
+ end
72
+ end
73
+
74
+ describe '#form_of_be_falsey=' do
75
+ ['be_falsey', 'be_falsy'] .each do |form|
76
+ context "when #{form.inspect} is passed" do
77
+ it "sets #{form.inspect}" do
78
+ configuration.form_of_be_falsey = form
79
+ configuration.form_of_be_falsey.should == form
80
+ end
81
+ end
82
+ end
83
+
84
+ context 'when a form other than "be_falsey" or "be_falsy" is passed' do
85
+ it 'raises error' do
86
+ lambda do
87
+ configuration.form_of_be_falsey = 'foo'
88
+ end.should raise_error(ArgumentError)
89
+ end
90
+ end
91
+ end
57
92
  end
58
93
  end
@@ -5,7 +5,8 @@ require 'transpec/converter'
5
5
 
6
6
  module Transpec
7
7
  describe Converter do
8
- subject(:converter) { Converter.new(configuration) }
8
+ subject(:converter) { Converter.new(configuration, rspec_version) }
9
+ let(:rspec_version) { Transpec.current_rspec_version }
9
10
  let(:configuration) { Configuration.new }
10
11
 
11
12
  describe '#convert_file!' do
@@ -380,8 +381,8 @@ module Transpec
380
381
  let(:method_stub_object) { double('method_stub_object').as_null_object }
381
382
 
382
383
  shared_examples 'invokes MethodStub#allowize!' do
383
- it 'invokes MethodStub#allowize!' do
384
- method_stub_object.should_receive(:allowize!)
384
+ it 'invokes MethodStub#allowize! with #receive_messages availability' do
385
+ method_stub_object.should_receive(:allowize!).with(rspec_version.receive_messages_available?)
385
386
  converter.process_method_stub(method_stub_object)
386
387
  end
387
388
  end
@@ -484,6 +485,69 @@ module Transpec
484
485
  end
485
486
  end
486
487
 
488
+ describe '#process_be_boolean' do
489
+ let(:be_boolean_object) { double('be_boolean_object').as_null_object }
490
+
491
+ context 'when RSpecVersion#be_truthy_available? returns true' do
492
+ before { rspec_version.stub(:be_truthy_available?).and_return(true) }
493
+
494
+ context 'when Configuration#convert_deprecated_method? is true' do
495
+ before { configuration.convert_deprecated_method = true }
496
+
497
+ context 'and Configuration#boolean_matcher_type is :conditional' do
498
+ before { configuration.boolean_matcher_type = :conditional }
499
+
500
+ context 'and Configuration#form_of_be_falsey is "be_falsey"' do
501
+ before { configuration.form_of_be_falsey = 'be_falsey' }
502
+
503
+ it 'invokes BeBoolean#convert_to_conditional_matcher! with "be_falsey"' do
504
+ be_boolean_object.should_receive(:convert_to_conditional_matcher!).with('be_falsey')
505
+ converter.process_be_boolean(be_boolean_object)
506
+ end
507
+ end
508
+
509
+ context 'and Configuration#form_of_be_falsey is "be_falsy"' do
510
+ before { configuration.form_of_be_falsey = 'be_falsy' }
511
+
512
+ it 'invokes BeBoolean#convert_to_conditional_matcher! with "be_falsy"' do
513
+ be_boolean_object.should_receive(:convert_to_conditional_matcher!).with('be_falsy')
514
+ converter.process_be_boolean(be_boolean_object)
515
+ end
516
+ end
517
+ end
518
+
519
+ context 'and Configuration#boolean_matcher_type is :exact' do
520
+ before { configuration.boolean_matcher_type = :exact }
521
+
522
+ it 'invokes BeBoolean#convert_to_exact_matcher!' do
523
+ be_boolean_object.should_receive(:convert_to_exact_matcher!)
524
+ converter.process_be_boolean(be_boolean_object)
525
+ end
526
+ end
527
+ end
528
+
529
+ context 'when Configuration#convert_deprecated_method? is false' do
530
+ before { configuration.convert_deprecated_method = false }
531
+
532
+ it 'does nothing' do
533
+ be_boolean_object.should_not_receive(:convert_to_conditional_matcher!)
534
+ be_boolean_object.should_not_receive(:convert_to_exact_matcher!)
535
+ converter.process_be_boolean(be_boolean_object)
536
+ end
537
+ end
538
+ end
539
+
540
+ context 'when RSpecVersion#be_truthy_available? returns true' do
541
+ before { rspec_version.stub(:be_truthy_available?).and_return(false) }
542
+
543
+ it 'does nothing' do
544
+ be_boolean_object.should_not_receive(:convert_to_conditional_matcher!)
545
+ be_boolean_object.should_not_receive(:convert_to_exact_matcher!)
546
+ converter.process_be_boolean(be_boolean_object)
547
+ end
548
+ end
549
+ end
550
+
487
551
  describe '#process_be_close' do
488
552
  let(:be_close_object) { double('be_close_object').as_null_object }
489
553
 
@@ -496,7 +560,7 @@ module Transpec
496
560
  end
497
561
  end
498
562
 
499
- context 'when Configuration#convert_deprecated_method? is true' do
563
+ context 'when Configuration#convert_deprecated_method? is false' do
500
564
  before { configuration.convert_deprecated_method = false }
501
565
 
502
566
  it 'does not invoke BeClose#convert_to_be_within!' do
@@ -518,7 +582,7 @@ module Transpec
518
582
  end
519
583
  end
520
584
 
521
- context 'when Configuration#convert_deprecated_method? is true' do
585
+ context 'when Configuration#convert_deprecated_method? is false' do
522
586
  before { configuration.convert_deprecated_method = false }
523
587
 
524
588
  it 'does not invoke BeClose#convert_to_be_within!' do
@@ -540,7 +604,7 @@ module Transpec
540
604
  end
541
605
  end
542
606
 
543
- context 'when Configuration#convert_its? is true' do
607
+ context 'when Configuration#convert_its? is false' do
544
608
  before { configuration.convert_its = false }
545
609
 
546
610
  it 'does not invoke Its#convert_to_describe_subject_it!' do
@@ -105,7 +105,7 @@ module Transpec
105
105
  context "when #{form.inspect} is specified" do
106
106
  let(:args) { ['--negative-form', form] }
107
107
 
108
- it "sets Configuration#negative_form_of_to? #{form.inspect}" do
108
+ it "sets Configuration#negative_form_of_to #{form.inspect}" do
109
109
  parser.parse(args)
110
110
  configuration.negative_form_of_to.should == form
111
111
  end
@@ -113,6 +113,38 @@ module Transpec
113
113
  end
114
114
  end
115
115
 
116
+ describe '-b/--boolean-matcher option' do
117
+ [
118
+ ['truthy,falsey', :conditional, 'be_falsey'],
119
+ ['truthy,falsy', :conditional, 'be_falsy'],
120
+ ['true,false', :exact, 'be_falsey']
121
+ ].each do |cli_type, configuration_type, form_of_be_falsey|
122
+ context "when #{cli_type.inspect} is specified" do
123
+ let(:args) { ['--boolean-matcher', cli_type] }
124
+
125
+ it "sets Configuration#boolean_matcher_type #{configuration_type.inspect}" do
126
+ parser.parse(args)
127
+ configuration.boolean_matcher_type.should == configuration_type
128
+ end
129
+
130
+ it "sets Configuration#form_of_be_falsey #{form_of_be_falsey.inspect}" do
131
+ parser.parse(args)
132
+ configuration.form_of_be_falsey.should == form_of_be_falsey
133
+ end
134
+ end
135
+ end
136
+
137
+ ['', 'truthy', 'true', 'foo'].each do |cli_type|
138
+ context "when #{cli_type.inspect} is specified" do
139
+ let(:args) { ['--boolean-matcher', cli_type] }
140
+
141
+ it 'raises error' do
142
+ -> { parser.parse(args) }.should raise_error(/must be any of/)
143
+ end
144
+ end
145
+ end
146
+ end
147
+
116
148
  describe '-p/--no-parentheses-matcher-arg option' do
117
149
  let(:args) { ['--no-parentheses-matcher-arg'] }
118
150
 
@@ -0,0 +1,73 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'transpec/project'
5
+
6
+ module Transpec
7
+ describe Project do
8
+ include FileHelper
9
+ include CacheHelper
10
+
11
+ subject(:project) { Project.new }
12
+
13
+ describe '#require_bundler?' do
14
+ include_context 'isolated environment'
15
+
16
+ subject { project.require_bundler? }
17
+
18
+ context 'when the project has a Gemfile' do
19
+ before do
20
+ create_file('Gemfile', '')
21
+ end
22
+
23
+ it { should be_true }
24
+ end
25
+
26
+ context 'when the project have no Gemfile' do
27
+ it { should be_false }
28
+ end
29
+ end
30
+
31
+ describe '#rspec_version' do
32
+ subject(:rspec_version) { project.rspec_version }
33
+
34
+ it 'returns an instance of RSpecVersion' do
35
+ should be_a(RSpecVersion)
36
+ end
37
+
38
+ context 'when the project has a Gemfile' do
39
+ context 'and depends on RSpec 2.13.0' do
40
+ around do |example|
41
+ with_cached_dir('rspec-2.13.0-project') do |cached|
42
+ unless cached
43
+ create_file('Gemfile', [
44
+ "source 'https://rubygems.org'",
45
+ "gem 'rspec-core', '2.13.0'"
46
+ ])
47
+
48
+ project.with_bundler_clean_env do
49
+ `bundle install --path vendor/bundle`
50
+ end
51
+ end
52
+
53
+ example.run
54
+ end
55
+ end
56
+
57
+ it 'returns the version' do
58
+ rspec_version.to_s.should == '2.13.0'
59
+ end
60
+ end
61
+ end
62
+
63
+ context 'when the project has no Gemfile' do
64
+ include_context 'isolated environment'
65
+
66
+ it 'returns version of the RSpec that is installed in the system' do
67
+ require 'rspec/core/version'
68
+ rspec_version.to_s.should == RSpec::Core::Version::STRING
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,44 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'transpec/rspec_version'
5
+
6
+ module Transpec
7
+ describe RSpecVersion do
8
+ subject(:rspec_version) { RSpecVersion.new(version_string) }
9
+
10
+ describe '#be_truthy_available?' do
11
+ subject { rspec_version.be_truthy_available? }
12
+
13
+ [
14
+ ['2.14.0', false],
15
+ ['2.99.0.beta.1', true],
16
+ ['2.99.0', true],
17
+ ['3.0.0.beta.1', true],
18
+ ['3.0.0', true]
19
+ ].each do |version, expected|
20
+ context "when the version is #{version}" do
21
+ let(:version_string) { version }
22
+ it { should == expected }
23
+ end
24
+ end
25
+ end
26
+
27
+ describe '#receive_messages_available?' do
28
+ subject { rspec_version.receive_messages_available? }
29
+
30
+ [
31
+ ['2.14.0', false],
32
+ ['2.99.0.beta.1', false],
33
+ ['2.99.0', false],
34
+ ['3.0.0.beta.1', true],
35
+ ['3.0.0', true]
36
+ ].each do |version, expected|
37
+ context "when the version is #{version}" do
38
+ let(:version_string) { version }
39
+ it { should == expected }
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end