transpec 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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