rspec-rails 2.13.0 → 2.13.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/Capybara.md +1 -3
  3. data/Changelog.md +14 -0
  4. data/README.md +46 -16
  5. data/features/Transactions.md +2 -2
  6. data/features/Upgrade.md +4 -0
  7. data/features/controller_specs/Cookies.md +1 -1
  8. data/features/controller_specs/README.md +9 -9
  9. data/features/controller_specs/controller_spec.feature +1 -1
  10. data/features/controller_specs/engine_routes.feature +51 -0
  11. data/features/helper_specs/helper_spec.feature +26 -0
  12. data/features/matchers/README.md +3 -3
  13. data/features/model_specs/errors_on.feature +1 -1
  14. data/features/routing_specs/README.md +6 -7
  15. data/features/routing_specs/engine_routes.feature +38 -0
  16. data/features/support/rails_versions.rb +4 -0
  17. data/lib/generators/rspec.rb +2 -1
  18. data/lib/generators/rspec/controller/controller_generator.rb +1 -1
  19. data/lib/generators/rspec/install/install_generator.rb +2 -0
  20. data/lib/generators/rspec/install/templates/spec/spec_helper.rb.tt +2 -2
  21. data/lib/generators/rspec/scaffold/scaffold_generator.rb +1 -1
  22. data/lib/generators/rspec/scaffold/templates/controller_spec.rb +4 -8
  23. data/lib/rspec/rails.rb +1 -0
  24. data/lib/rspec/rails/adapters.rb +30 -1
  25. data/lib/rspec/rails/example/controller_example_group.rb +43 -6
  26. data/lib/rspec/rails/example/rails_example_group.rb +2 -0
  27. data/lib/rspec/rails/example/routing_example_group.rb +28 -2
  28. data/lib/rspec/rails/example/view_example_group.rb +1 -1
  29. data/lib/rspec/rails/fixture_support.rb +1 -0
  30. data/lib/rspec/rails/matchers/routing_matchers.rb +1 -1
  31. data/lib/rspec/rails/mocks.rb +1 -1
  32. data/lib/rspec/rails/rails_version.rb +17 -0
  33. data/lib/rspec/rails/tasks/rspec.rake +8 -6
  34. data/lib/rspec/rails/version.rb +1 -1
  35. data/spec/generators/rspec/controller/controller_generator_spec.rb +11 -0
  36. data/spec/generators/rspec/install/install_generator_spec.rb +1 -1
  37. data/spec/generators/rspec/scaffold/scaffold_generator_spec.rb +23 -0
  38. data/spec/rspec/rails/assertion_delegator_spec.rb +13 -0
  39. data/spec/rspec/rails/example/view_example_group_spec.rb +1 -1
  40. data/spec/rspec/rails/matchers/have_rendered_spec.rb +3 -3
  41. data/spec/rspec/rails/matchers/relation_match_array_spec.rb +1 -1
  42. data/spec/rspec/rails/matchers/route_to_spec.rb +9 -10
  43. data/spec/rspec/rails/minitest_lifecycle_adapter_spec.rb +22 -0
  44. data/spec/rspec/rails/rails_version_spec.rb +29 -0
  45. data/spec/support/null_object.rb +6 -0
  46. metadata +67 -86
@@ -6,9 +6,9 @@ require 'rspec/autorun'
6
6
 
7
7
  # Requires supporting ruby files with custom matchers and macros, etc,
8
8
  # in spec/support/ and its subdirectories.
9
- Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
9
+ Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
10
10
 
11
- <% if ::Rails.version >= '4' -%>
11
+ <% if RSpec::Rails.rails_version_satisfied_by?('>= 4.0.0.beta1') -%>
12
12
  # Checks for pending migrations before tests are run.
13
13
  # If you are not using ActiveRecord, you can remove this line.
14
14
  ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
@@ -27,7 +27,7 @@ module Rspec
27
27
  end
28
28
 
29
29
  def generate_view_specs
30
- return unless options[:view_specs]
30
+ return unless options[:view_specs] && options[:template_engine]
31
31
 
32
32
  copy_view :edit
33
33
  copy_view :index unless options[:singleton]
@@ -23,17 +23,13 @@ describe <%= controller_class_name %>Controller do
23
23
 
24
24
  # This should return the minimal set of attributes required to create a valid
25
25
  # <%= class_name %>. As you add validations to <%= class_name %>, be sure to
26
- # update the return value of this method accordingly.
27
- def valid_attributes
28
- <%= formatted_hash(example_valid_attributes) %>
29
- end
26
+ # adjust the attributes here as well.
27
+ let(:valid_attributes) { <%= formatted_hash(example_valid_attributes) %> }
30
28
 
31
29
  # This should return the minimal set of values that should be in the session
32
30
  # in order to pass any filters (e.g. authentication) defined in
33
31
  # <%= controller_class_name %>Controller. Be sure to keep this updated too.
34
- def valid_session
35
- {}
36
- end
32
+ let(:valid_session) { {} }
37
33
 
38
34
  <% unless options[:singleton] -%>
39
35
  describe "GET index" do
@@ -113,7 +109,7 @@ describe <%= controller_class_name %>Controller do
113
109
  # specifies that the <%= class_name %> created on the previous line
114
110
  # receives the :update_attributes message with whatever params are
115
111
  # submitted in the request.
116
- <%- if Rails.version >= '4' -%>
112
+ <%- if RSpec::Rails.rails_version_satisfied_by?('>= 4.0.0.beta1') -%>
117
113
  <%= class_name %>.any_instance.should_receive(:update).with(<%= formatted_hash(example_params_for_update) %>)
118
114
  <%- else -%>
119
115
  <%= class_name %>.any_instance.should_receive(:update_attributes).with(<%= formatted_hash(example_params_for_update) %>)
@@ -5,6 +5,7 @@ RSpec::configure do |c|
5
5
  c.backtrace_clean_patterns << /lib\/rspec\/rails/
6
6
  end
7
7
 
8
+ require 'rspec/rails/rails_version'
8
9
  require 'rspec/rails/extensions'
9
10
  require 'rspec/rails/view_rendering'
10
11
  require 'rspec/rails/adapters'
@@ -24,7 +24,8 @@ module RSpec
24
24
  end
25
25
 
26
26
  assertion_modules.each do |mod|
27
- mod.instance_methods.each do |method|
27
+ mod.public_instance_methods.each do |method|
28
+ next if method == :method_missing || method == "method_missing"
28
29
  class_eval <<-EOM, __FILE__, __LINE__ + 1
29
30
  def #{method}(*args, &block)
30
31
  assertion_instance.send(:#{method}, *args, &block)
@@ -36,6 +37,34 @@ module RSpec
36
37
  end
37
38
  end
38
39
 
40
+ # MiniTest::Unit::LifecycleHooks
41
+ module MiniTestLifecycleAdapter
42
+ extend ActiveSupport::Concern
43
+
44
+ included do |group|
45
+ group.before { after_setup }
46
+ group.after { before_teardown }
47
+
48
+ group.around do |example|
49
+ before_setup
50
+ example.run
51
+ after_teardown
52
+ end
53
+ end
54
+
55
+ def before_setup
56
+ end
57
+
58
+ def after_setup
59
+ end
60
+
61
+ def before_teardown
62
+ end
63
+
64
+ def after_teardown
65
+ end
66
+ end
67
+
39
68
  module SetupAndTeardownAdapter
40
69
  extend ActiveSupport::Concern
41
70
 
@@ -11,6 +11,7 @@ module RSpec::Rails
11
11
  include RSpec::Rails::Matchers::RedirectTo
12
12
  include RSpec::Rails::Matchers::RenderTemplate
13
13
  include RSpec::Rails::Matchers::RoutingMatchers
14
+ include RSpec::Rails::AssertionDelegator.new(ActionDispatch::Assertions::RoutingAssertions)
14
15
 
15
16
  module ClassMethods
16
17
  # @private
@@ -64,18 +65,43 @@ module RSpec::Rails
64
65
  metadata[:example_group][:described_class].class_eval(&body)
65
66
 
66
67
  before do
67
- @orig_routes, @routes = @routes, ActionDispatch::Routing::RouteSet.new
68
- @routes.draw { resources :anonymous }
68
+ @orig_routes = self.routes
69
+ self.routes = ActionDispatch::Routing::RouteSet.new.tap { |r|
70
+ r.draw { resources :anonymous }
71
+ }
69
72
  end
70
73
 
71
74
  after do
72
- @routes, @orig_routes = @orig_routes, nil
75
+ self.routes = @orig_routes
76
+ @orig_routes = nil
77
+ end
78
+ end
79
+
80
+ # Specifies the routeset that will be used for the example group. This
81
+ # is most useful when testing Rails engines.
82
+ #
83
+ # @example
84
+ #
85
+ # describe MyEngine::PostsController do
86
+ # routes { MyEngine::Engine.routes }
87
+ #
88
+ # # ...
89
+ # end
90
+ def routes(&blk)
91
+ before do
92
+ self.routes = blk.call
73
93
  end
74
94
  end
75
95
  end
76
96
 
77
97
  attr_reader :controller, :routes
78
98
 
99
+ # @api private
100
+ def routes=(routes)
101
+ @routes = routes
102
+ assertion_instance.instance_variable_set(:@routes, routes)
103
+ end
104
+
79
105
  module BypassRescue
80
106
  def rescue_with_handler(exception)
81
107
  raise exception
@@ -107,7 +133,9 @@ module RSpec::Rails
107
133
  # If method is a named_route, delegates to the RouteSet associated with
108
134
  # this controller.
109
135
  def method_missing(method, *args, &block)
110
- if @orig_routes && @orig_routes.named_routes.helpers.include?(method)
136
+ if @routes && @routes.named_routes.helpers.include?(method)
137
+ controller.send(method, *args, &block)
138
+ elsif @orig_routes && @orig_routes.named_routes.helpers.include?(method)
111
139
  controller.send(method, *args, &block)
112
140
  else
113
141
  super
@@ -120,8 +148,17 @@ module RSpec::Rails
120
148
  metadata[:type] = :controller
121
149
 
122
150
  before do
123
- @routes = ::Rails.application.routes
124
- ActionController::Base.allow_forgery_protection = false
151
+ self.routes = ::Rails.application.routes
152
+ end
153
+
154
+ around do |ex|
155
+ previous_allow_forgery_protection_value = ActionController::Base.allow_forgery_protection
156
+ begin
157
+ ActionController::Base.allow_forgery_protection = false
158
+ ex.call
159
+ ensure
160
+ ActionController::Base.allow_forgery_protection = previous_allow_forgery_protection_value
161
+ end
125
162
  end
126
163
  end
127
164
  end
@@ -1,12 +1,14 @@
1
1
  # Temporary workaround to resolve circular dependency between rspec-rails' spec
2
2
  # suite and ammeter.
3
3
  require 'rspec/rails/matchers'
4
+ require 'rspec/rails/rails_version'
4
5
 
5
6
  module RSpec
6
7
  module Rails
7
8
  module RailsExampleGroup
8
9
  extend ActiveSupport::Concern
9
10
  include RSpec::Rails::SetupAndTeardownAdapter
11
+ include RSpec::Rails::MiniTestLifecycleAdapter if RSpec::Rails.rails_version_satisfied_by?('>= 4.0.0.beta1')
10
12
  include RSpec::Rails::TestUnitAssertionAdapter
11
13
  include RSpec::Rails::Matchers
12
14
  end
@@ -8,17 +8,43 @@ module RSpec::Rails
8
8
  include RSpec::Rails::Matchers::RoutingMatchers::RouteHelpers
9
9
  include RSpec::Rails::AssertionDelegator.new(ActionDispatch::Assertions::RoutingAssertions)
10
10
 
11
+ module ClassMethods
12
+ # Specifies the routeset that will be used for the example group. This
13
+ # is most useful when testing Rails engines.
14
+ #
15
+ # @example
16
+ #
17
+ # describe MyEngine::PostsController do
18
+ # routes { MyEngine::Engine.routes }
19
+ #
20
+ # it "routes posts#index" do
21
+ # expect(:get => "/posts").to
22
+ # route_to(:controller => "my_engine/posts", :action => "index")
23
+ # end
24
+ # end
25
+ def routes(&blk)
26
+ before do
27
+ self.routes = blk.call
28
+ end
29
+ end
30
+ end
31
+
11
32
  included do
12
33
  metadata[:type] = :routing
13
34
 
14
35
  before do
15
- @routes = ::Rails.application.routes
16
- assertion_instance.instance_variable_set(:@routes, @routes)
36
+ self.routes = ::Rails.application.routes
17
37
  end
18
38
  end
19
39
 
20
40
  attr_reader :routes
21
41
 
42
+ # @api private
43
+ def routes=(routes)
44
+ @routes = routes
45
+ assertion_instance.instance_variable_set(:@routes, routes)
46
+ end
47
+
22
48
  private
23
49
 
24
50
  def method_missing(m, *args, &block)
@@ -107,7 +107,7 @@ module RSpec::Rails
107
107
  end
108
108
 
109
109
  def _default_render_options
110
- if ::Rails.version >= "3.2"
110
+ if RSpec::Rails.rails_version_satisfied_by?('>= 3.2')
111
111
  # pluck the handler, format, and locale out of, eg, posts/index.de.html.haml
112
112
  template, *components = _default_file_to_render.split('.')
113
113
  handler, format, locale = *components.reverse
@@ -4,6 +4,7 @@ module RSpec
4
4
  module FixtureSupport
5
5
  extend ActiveSupport::Concern
6
6
  include RSpec::Rails::SetupAndTeardownAdapter
7
+ include RSpec::Rails::MiniTestLifecycleAdapter if RSpec::Rails.rails_version_satisfied_by?('>= 4.0.0.beta1')
7
8
  include RSpec::Rails::TestUnitAssertionAdapter
8
9
  include ActiveRecord::TestFixtures
9
10
 
@@ -97,7 +97,7 @@ module RSpec::Rails::Matchers
97
97
  end
98
98
 
99
99
  module RouteHelpers
100
- %w(get post put delete options head).each do |method|
100
+ %w(get post put patch delete options head).each do |method|
101
101
  define_method method do |path|
102
102
  { method.to_sym => path }
103
103
  end
@@ -96,7 +96,7 @@ EOM
96
96
  :valid? => true,
97
97
  :blank? => false)
98
98
 
99
- mock("#{model_class.name}_#{stubs[:id]}", stubs).tap do |m|
99
+ double("#{model_class.name}_#{stubs[:id]}", stubs).tap do |m|
100
100
  m.singleton_class.class_eval do
101
101
  include ActiveModelInstanceMethods
102
102
  include ActiveRecordInstanceMethods if defined?(ActiveRecord)
@@ -0,0 +1,17 @@
1
+ module RSpec
2
+ module Rails
3
+ # @api private
4
+ def self.rails_version_satisfied_by?(requirement)
5
+ Gem::Requirement.new(requirement).satisfied_by?(rails_version)
6
+ end
7
+
8
+ # @api private
9
+ def self.rails_version
10
+ @rails_version ||= if ::Rails.version.is_a?(Gem::Version)
11
+ ::Rails.version
12
+ else
13
+ Gem::Version.new(::Rails.version.to_s)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -25,11 +25,14 @@ namespace :spec do
25
25
  end
26
26
  end
27
27
 
28
- desc "Run all specs with rcov"
29
- RSpec::Core::RakeTask.new(:rcov => spec_prereq) do |t|
30
- t.rcov = true
31
- t.pattern = "./spec/**/*_spec.rb"
32
- t.rcov_opts = '--exclude /gems/,/Library/,/usr/,lib/tasks,.bundle,config,/lib/rspec/,/lib/rspec-,spec'
28
+ # RCov task only enabled for Ruby 1.8
29
+ if RUBY_VERSION < '1.9'
30
+ desc "Run all specs with rcov"
31
+ RSpec::Core::RakeTask.new(:rcov => spec_prereq) do |t|
32
+ t.rcov = true
33
+ t.pattern = "./spec/**/*_spec.rb"
34
+ t.rcov_opts = '--exclude /gems/,/Library/,/usr/,lib/tasks,.bundle,config,/lib/rspec/,/lib/rspec-,spec'
35
+ end
33
36
  end
34
37
 
35
38
  task :statsetup do
@@ -42,4 +45,3 @@ namespace :spec do
42
45
  end
43
46
  end
44
47
  end
45
-
@@ -1,7 +1,7 @@
1
1
  module RSpec
2
2
  module Rails
3
3
  module Version
4
- STRING = '2.13.0'
4
+ STRING = '2.13.1'
5
5
  end
6
6
  end
7
7
  end
@@ -50,6 +50,17 @@ describe Rspec::Generators::ControllerGenerator do
50
50
  it { should_not exist }
51
51
  end
52
52
  end
53
+
54
+ describe 'with --no-template-engine' do
55
+ before do
56
+ run_generator %w(posts index --no-template-engine)
57
+ end
58
+
59
+ describe 'index.html.erb' do
60
+ subject { file('spec/views/posts/index.html._spec.rb') }
61
+ it { should_not exist }
62
+ end
63
+ end
53
64
  end
54
65
 
55
66
  describe 'are generated' do
@@ -16,7 +16,7 @@ describe Rspec::Generators::InstallGenerator do
16
16
  File.read( file('spec/spec_helper.rb') ).should =~ /^require 'rspec\/autorun'$/m
17
17
  end
18
18
 
19
- if ::Rails.version >= '4'
19
+ if RSpec::Rails.rails_version_satisfied_by?('>= 4.0.0.beta1')
20
20
  it "generates spec/spec_helper.rb with a check for pending migrations" do
21
21
  run_generator
22
22
  File.read( file('spec/spec_helper.rb') ).should =~ /ActiveRecord::Migration\.check_pending!/m
@@ -72,6 +72,29 @@ describe Rspec::Generators::ScaffoldGenerator do
72
72
  end
73
73
  end
74
74
 
75
+ describe 'with --no-template-engine' do
76
+ before { run_generator %w(posts --no-template-engine) }
77
+ describe 'edit' do
78
+ subject { file("spec/views/posts/edit.html._spec.rb") }
79
+ it { should_not exist }
80
+ end
81
+
82
+ describe 'index' do
83
+ subject { file("spec/views/posts/index.html._spec.rb") }
84
+ it { should_not exist }
85
+ end
86
+
87
+ describe 'new' do
88
+ subject { file("spec/views/posts/new.html._spec.rb") }
89
+ it { should_not exist }
90
+ end
91
+
92
+ describe 'show' do
93
+ subject { file("spec/views/posts/show.html._spec.rb") }
94
+ it { should_not exist }
95
+ end
96
+ end
97
+
75
98
  describe 'with --no-view-specs' do
76
99
  before { run_generator %w(posts --no-view-specs) }
77
100
 
@@ -27,4 +27,17 @@ describe RSpec::Rails::AssertionDelegator do
27
27
  expect(klass.new).to have_thing(:a)
28
28
  expect(klass.new).not_to have_thing(:b)
29
29
  end
30
+
31
+ it "does not delegate method_missing" do
32
+ assertions = Module.new {
33
+ def method_missing(method, *args)
34
+ end
35
+ }
36
+
37
+ klass = Class.new {
38
+ include RSpec::Rails::AssertionDelegator.new(assertions)
39
+ }
40
+
41
+ expect { klass.new.abc123 }.to raise_error(NoMethodError)
42
+ end
30
43
  end
@@ -118,7 +118,7 @@ module RSpec::Rails
118
118
  view_spec.stub(:_default_file_to_render) { "widgets/new.en.html.erb" }
119
119
  view_spec.render
120
120
 
121
- if ::Rails.version >= "3.2"
121
+ if RSpec::Rails.rails_version_satisfied_by?('>= 3.2')
122
122
  view_spec.received.first.should == [{:template => "widgets/new", :locales=>['en'], :formats=>['html'], :handlers=>['erb']}, {}, nil]
123
123
  else
124
124
  view_spec.received.first.should == [{:template => "widgets/new.en.html.erb"}, {}, nil]
@@ -29,7 +29,7 @@ require "spec_helper"
29
29
  context "with should" do
30
30
  context "when assert_template passes" do
31
31
  it "passes" do
32
- self.stub!(:assert_template)
32
+ def assert_template(*); end
33
33
  expect do
34
34
  expect(response).to send(template_expectation, "template_name")
35
35
  end.to_not raise_exception
@@ -38,7 +38,7 @@ require "spec_helper"
38
38
 
39
39
  context "when assert_template fails" do
40
40
  it "uses failure message from assert_template" do
41
- self.stub!(:assert_template) do
41
+ def assert_template(*)
42
42
  raise ActiveSupport::TestCase::Assertion.new("this message")
43
43
  end
44
44
  expect do
@@ -49,7 +49,7 @@ require "spec_helper"
49
49
 
50
50
  context "when fails due to some other exception" do
51
51
  it "raises that exception" do
52
- self.stub!(:assert_template) do
52
+ def assert_template(*)
53
53
  raise "oops"
54
54
  end
55
55
  expect do