rspec-rails 2.6.1 → 2.7.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/README.md +5 -5
  2. data/features/Transactions.md +84 -0
  3. data/features/controller_specs/Cookies.md +57 -0
  4. data/features/controller_specs/anonymous_controller.feature +104 -61
  5. data/features/controller_specs/bypass_rescue.feature +75 -0
  6. data/features/matchers/relation_match_array.feature +20 -0
  7. data/features/mocks/mock_model.feature +6 -6
  8. data/features/support/env.rb +2 -2
  9. data/features/view_specs/view_spec.feature +2 -8
  10. data/lib/autotest/rails_rspec2.rb +1 -1
  11. data/lib/generators/rspec/controller/templates/controller_spec.rb +1 -1
  12. data/lib/generators/rspec/install/templates/spec/spec_helper.rb +6 -0
  13. data/lib/generators/rspec/scaffold/templates/controller_spec.rb +6 -6
  14. data/lib/generators/rspec/view/templates/view_spec.rb +1 -1
  15. data/lib/rspec/rails/example/controller_example_group.rb +19 -1
  16. data/lib/rspec/rails/fixture_support.rb +11 -0
  17. data/lib/rspec/rails/matchers.rb +1 -0
  18. data/lib/rspec/rails/matchers/relation_match_array.rb +3 -0
  19. data/lib/rspec/rails/matchers/routing_matchers.rb +16 -14
  20. data/lib/rspec/rails/mocks.rb +12 -7
  21. data/lib/rspec/rails/version.rb +1 -1
  22. data/spec/generators/rspec/controller/controller_generator_spec.rb +86 -0
  23. data/spec/generators/rspec/helper/helper_generator_spec.rb +30 -0
  24. data/spec/generators/rspec/install/install_generator_spec.rb +18 -0
  25. data/spec/generators/rspec/integration/integration_generator_spec.rb +44 -0
  26. data/spec/generators/rspec/mailer/mailer_generator_spec.rb +48 -0
  27. data/spec/generators/rspec/model/model_generator_spec.rb +52 -0
  28. data/spec/generators/rspec/observer/observer_generator_spec.rb +21 -0
  29. data/spec/generators/rspec/scaffold/scaffold_generator_spec.rb +113 -0
  30. data/spec/generators/rspec/view/view_generator_spec.rb +41 -0
  31. data/spec/rspec/rails/example/controller_example_group_spec.rb +39 -3
  32. data/spec/rspec/rails/matchers/relation_match_array_spec.rb +19 -0
  33. data/spec/rspec/rails/matchers/route_to_spec.rb +25 -3
  34. data/spec/rspec/rails/mocks/mock_model_spec.rb +62 -2
  35. data/spec/rspec/rails/mocks/stub_model_spec.rb +0 -1
  36. data/spec/spec_helper.rb +2 -1
  37. data/spec/{rspec/rails/mocks → support}/ar_classes.rb +5 -2
  38. metadata +102 -99
  39. data/.document +0 -5
  40. data/.gitignore +0 -14
  41. data/.rspec +0 -1
  42. data/.travis.yml +0 -11
  43. data/History.md +0 -1
  44. data/License.txt +0 -23
  45. data/README_DEV.md +0 -43
  46. data/Rakefile +0 -152
  47. data/Thorfile +0 -45
  48. data/Upgrade.md +0 -1
  49. data/cucumber.yml +0 -3
  50. data/features/.nav +0 -35
  51. data/features/Changelog.md +0 -162
  52. data/gemfiles/.bundle/config +0 -2
  53. data/gemfiles/base.rb +0 -60
  54. data/gemfiles/rails-3-0-stable +0 -6
  55. data/gemfiles/rails-3.0.0 +0 -5
  56. data/gemfiles/rails-3.0.1 +0 -5
  57. data/gemfiles/rails-3.0.2 +0 -5
  58. data/gemfiles/rails-3.0.3 +0 -5
  59. data/gemfiles/rails-3.0.4 +0 -5
  60. data/gemfiles/rails-3.0.5 +0 -5
  61. data/gemfiles/rails-3.0.6 +0 -5
  62. data/gemfiles/rails-3.0.7 +0 -5
  63. data/gemfiles/rails-3.1.0.rc1 +0 -5
  64. data/gemfiles/rails-master +0 -5
  65. data/rspec-rails.gemspec +0 -34
  66. data/templates/generate_stuff.rb +0 -21
  67. data/templates/run_specs.rb +0 -9
@@ -0,0 +1,20 @@
1
+ Feature: ActiveRecord::Relation match array
2
+
3
+ The `=~` matcher can be used with an `ActiveRecord::Relation` (scope). The
4
+ assertion will pass if the scope would return all of the elements specified
5
+ in the array on the right hand side.
6
+
7
+ Scenario: example spec with relation =~ matcher
8
+ Given a file named "spec/models/widget_spec.rb" with:
9
+ """
10
+ require "spec_helper"
11
+
12
+ describe Widget do
13
+ let!(:widgets) { Array.new(3) { Widget.create } }
14
+ subject { Widget.scoped }
15
+
16
+ it { should =~ widgets }
17
+ end
18
+ """
19
+ When I run `rspec spec/models/widget_spec.rb`
20
+ Then the examples should all pass
@@ -1,13 +1,13 @@
1
1
  Feature: mock_model
2
2
 
3
- The mock_model method generates a test double that acts like an Active Model
4
- model. This is different from the stub_model method which generates an
5
- instance of a real ActiveModel class.
3
+ The `mock_model` method generates a test double that acts like an instance of
4
+ `ActiveModel`. This is different from the `stub_model` method which generates
5
+ an instance of a real model class.
6
6
 
7
- The benefit of mock_model over stub_model is that its a true double, so the
8
- examples are not dependent on the behaviour (or mis-behaviour), or even the
7
+ The benefit of `mock_model` over `stub_model` is that it is a true double, so
8
+ the examples are not dependent on the behavior (or mis-behavior), or even the
9
9
  existence of any other code. If you're working on a controller spec and you
10
- need a model that doesn't exist, you can pass mock_model a string and the
10
+ need a model that doesn't exist, you can pass `mock_model` a string and the
11
11
  generated object will act as though its an instance of the class named by
12
12
  that string.
13
13
 
@@ -2,14 +2,14 @@ require 'aruba/cucumber'
2
2
 
3
3
  module ArubaExt
4
4
  def run(cmd)
5
- super(cmd =~ /^rspec/ ? "bundle exec #{cmd}" : cmd)
5
+ super(cmd =~ /^rspec/ ? "bin/#{cmd}" : cmd)
6
6
  end
7
7
  end
8
8
 
9
9
  World(ArubaExt)
10
10
 
11
11
  Before do
12
- @aruba_timeout_seconds = 10
12
+ @aruba_timeout_seconds = 15
13
13
  end
14
14
 
15
15
  unless File.directory?('./tmp/example_app')
@@ -134,7 +134,7 @@ Feature: view spec
134
134
  When I run `rspec spec/views`
135
135
  Then the examples should all pass
136
136
 
137
- Scenario: spec with view that accesses helper_method helpers
137
+ Scenario: passing view spec that stubs a helper method
138
138
  Given a file named "app/views/secrets/index.html.erb" with:
139
139
  """
140
140
  <%- if admin? %>
@@ -147,13 +147,7 @@ Feature: view spec
147
147
 
148
148
  describe 'secrets/index.html.erb' do
149
149
  before do
150
- controller.singleton_class.class_eval do
151
- protected
152
- def admin?
153
- true
154
- end
155
- helper_method :admin?
156
- end
150
+ view.stub(:admin?).and_return(true)
157
151
  end
158
152
 
159
153
  it 'checks for admin access' do
@@ -42,7 +42,7 @@ class Autotest::RailsRspec2 < Autotest::Rspec2
42
42
  add_mapping(%r%^(test|spec)/fixtures/(.*).yml$%) { |_, m|
43
43
  ["spec/models/#{m[2].singularize}_spec.rb"] + files_matching(%r%^spec\/views\/#{m[2]}/.*_spec\.rb$%)
44
44
  }
45
- add_mapping(%r%^spec/(models|controllers|routing|views|helpers|mailers|requests|lib)/.*rb$%) { |filename, _|
45
+ add_mapping(%r%^spec/.*_spec\.rb$%) { |filename, _|
46
46
  filename
47
47
  }
48
48
  add_mapping(%r%^app/models/(.*)\.rb$%) { |_, m|
@@ -4,7 +4,7 @@ describe <%= class_name %>Controller do
4
4
 
5
5
  <% for action in actions -%>
6
6
  describe "GET '<%= action %>'" do
7
- it "should be successful" do
7
+ it "returns http success" do
8
8
  get '<%= action %>'
9
9
  response.should be_success
10
10
  end
@@ -2,6 +2,7 @@
2
2
  ENV["RAILS_ENV"] ||= 'test'
3
3
  require File.expand_path("../../config/environment", __FILE__)
4
4
  require 'rspec/rails'
5
+ require 'rspec/autorun'
5
6
 
6
7
  # Requires supporting ruby files with custom matchers and macros, etc,
7
8
  # in spec/support/ and its subdirectories.
@@ -24,4 +25,9 @@ RSpec.configure do |config|
24
25
  # examples within a transaction, remove the following line or assign false
25
26
  # instead of true.
26
27
  config.use_transactional_fixtures = true
28
+
29
+ # If true, the base class of anonymous controllers will be inferred
30
+ # automatically. This will be the default behavior in future versions of
31
+ # rspec-rails.
32
+ config.infer_base_class_for_anonymous_controllers = false
27
33
  end
@@ -40,7 +40,7 @@ describe <%= controller_class_name %>Controller do
40
40
  describe "GET show" do
41
41
  it "assigns the requested <%= ns_file_name %> as @<%= ns_file_name %>" do
42
42
  <%= file_name %> = <%= class_name %>.create! valid_attributes
43
- get :show, :id => <%= file_name %>.id.to_s
43
+ get :show, :id => <%= file_name %>.id
44
44
  assigns(:<%= ns_file_name %>).should eq(<%= file_name %>)
45
45
  end
46
46
  end
@@ -55,7 +55,7 @@ describe <%= controller_class_name %>Controller do
55
55
  describe "GET edit" do
56
56
  it "assigns the requested <%= ns_file_name %> as @<%= ns_file_name %>" do
57
57
  <%= file_name %> = <%= class_name %>.create! valid_attributes
58
- get :edit, :id => <%= file_name %>.id.to_s
58
+ get :edit, :id => <%= file_name %>.id
59
59
  assigns(:<%= ns_file_name %>).should eq(<%= file_name %>)
60
60
  end
61
61
  end
@@ -127,7 +127,7 @@ describe <%= controller_class_name %>Controller do
127
127
  <%= file_name %> = <%= class_name %>.create! valid_attributes
128
128
  # Trigger the behavior that occurs when invalid params are submitted
129
129
  <%= class_name %>.any_instance.stub(:save).and_return(false)
130
- put :update, :id => <%= file_name %>.id.to_s, :<%= ns_file_name %> => {}
130
+ put :update, :id => <%= file_name %>.id, :<%= ns_file_name %> => {}
131
131
  assigns(:<%= ns_file_name %>).should eq(<%= file_name %>)
132
132
  end
133
133
 
@@ -135,7 +135,7 @@ describe <%= controller_class_name %>Controller do
135
135
  <%= file_name %> = <%= class_name %>.create! valid_attributes
136
136
  # Trigger the behavior that occurs when invalid params are submitted
137
137
  <%= class_name %>.any_instance.stub(:save).and_return(false)
138
- put :update, :id => <%= file_name %>.id.to_s, :<%= ns_file_name %> => {}
138
+ put :update, :id => <%= file_name %>.id, :<%= ns_file_name %> => {}
139
139
  response.should render_template("edit")
140
140
  end
141
141
  end
@@ -145,13 +145,13 @@ describe <%= controller_class_name %>Controller do
145
145
  it "destroys the requested <%= ns_file_name %>" do
146
146
  <%= file_name %> = <%= class_name %>.create! valid_attributes
147
147
  expect {
148
- delete :destroy, :id => <%= file_name %>.id.to_s
148
+ delete :destroy, :id => <%= file_name %>.id
149
149
  }.to change(<%= class_name %>, :count).by(-1)
150
150
  end
151
151
 
152
152
  it "redirects to the <%= table_name %> list" do
153
153
  <%= file_name %> = <%= class_name %>.create! valid_attributes
154
- delete :destroy, :id => <%= file_name %>.id.to_s
154
+ delete :destroy, :id => <%= file_name %>.id
155
155
  response.should redirect_to(<%= index_helper %>_url)
156
156
  end
157
157
  end
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "<%= file_name %>/<%= @action %>.html.<%= options[:template_engine] %>" do
3
+ describe "<%= file_path %>/<%= @action %>.html.<%= options[:template_engine] %>" do
4
4
  pending "add some examples to (or delete) #{__FILE__}"
5
5
  end
@@ -1,3 +1,7 @@
1
+ RSpec.configure do |config|
2
+ config.add_setting :infer_base_class_for_anonymous_controllers, :default => false
3
+ end
4
+
1
5
  module RSpec::Rails
2
6
  # Extends ActionController::TestCase::Behavior to work with RSpec.
3
7
  #
@@ -124,7 +128,11 @@ module RSpec::Rails
124
128
  # +controller+ method. Any instance methods, filters, etc, that are
125
129
  # defined in +ApplicationController+, however, are accessible from within
126
130
  # the block.
127
- def controller(base_class = ApplicationController, &body)
131
+ def controller(base_class = nil, &body)
132
+ base_class ||= RSpec.configuration.infer_base_class_for_anonymous_controllers? ?
133
+ controller_class :
134
+ ApplicationController
135
+
128
136
  metadata[:example_group][:describes] = Class.new(base_class, &body)
129
137
  metadata[:example_group][:describes].singleton_class.class_eval do
130
138
  def name; "AnonymousController" end
@@ -144,6 +152,16 @@ module RSpec::Rails
144
152
  module InstanceMethods
145
153
  attr_reader :controller, :routes
146
154
 
155
+ module BypassRescue
156
+ def rescue_with_handler(exception)
157
+ raise exception
158
+ end
159
+ end
160
+
161
+ def bypass_rescue
162
+ controller.extend(BypassRescue)
163
+ end
164
+
147
165
  def method_missing(method, *args, &block)
148
166
  if @orig_routes && @orig_routes.named_routes.helpers.include?(method)
149
167
  controller.send(method, *args, &block)
@@ -9,6 +9,17 @@ module RSpec
9
9
  include ActiveRecord::TestFixtures
10
10
 
11
11
  included do
12
+ # TODO (DC 2011-06-25) this is necessary because fixture_file_upload
13
+ # accesses fixture_path directly on ActiveSupport::TestCase. This is
14
+ # fixed in rails by https://github.com/rails/rails/pull/1861, which
15
+ # should be part of the 3.1 release, at which point we can include
16
+ # these lines for rails < 3.1.
17
+ ActiveSupport::TestCase.class_eval do
18
+ include ActiveRecord::TestFixtures
19
+ self.fixture_path = RSpec.configuration.fixture_path
20
+ end
21
+ # /TODO
22
+
12
23
  self.fixture_path = RSpec.configuration.fixture_path
13
24
  self.use_transactional_fixtures = RSpec.configuration.use_transactional_fixtures
14
25
  self.use_instantiated_fixtures = RSpec.configuration.use_instantiated_fixtures
@@ -23,3 +23,4 @@ require 'rspec/rails/matchers/routing_matchers'
23
23
  require 'rspec/rails/matchers/be_new_record'
24
24
  require 'rspec/rails/matchers/be_a_new'
25
25
  require 'rspec/rails/matchers/have_extension'
26
+ require 'rspec/rails/matchers/relation_match_array'
@@ -0,0 +1,3 @@
1
+ if defined?(ActiveRecord)
2
+ RSpec::Matchers::OperatorMatcher.register(ActiveRecord::Relation, '=~', RSpec::Matchers::MatchArray)
3
+ end
@@ -2,26 +2,28 @@ module RSpec::Rails::Matchers
2
2
  module RoutingMatchers
3
3
  extend RSpec::Matchers::DSL
4
4
 
5
- matcher :route_to do |*route_options|
6
- match_unless_raises ActiveSupport::TestCase::Assertion do |path|
7
- assertion_path = { :method => path.keys.first, :path => path.values.first }
8
-
9
- path, options = *route_options
10
-
11
- if path.is_a?(String)
12
- controller, action = path.split("#")
13
- options ||= {}
14
- options.merge!(:controller => controller, :action => action)
15
- else
16
- options = path
17
- end
5
+ matcher :route_to do |*expected|
6
+ expected_options = expected[1] || {}
7
+ if Hash === expected[0]
8
+ expected_options.merge!(expected[0])
9
+ else
10
+ controller, action = expected[0].split('#')
11
+ expected_options.merge!(:controller => controller, :action => action)
12
+ end
18
13
 
19
- assert_recognizes(options, assertion_path)
14
+ match_unless_raises ActiveSupport::TestCase::Assertion do |verb_to_path_map|
15
+ path, query = *verb_to_path_map.values.first.split('?')
16
+ assert_recognizes(
17
+ expected_options,
18
+ {:method => verb_to_path_map.keys.first, :path => path},
19
+ Rack::Utils::parse_query(query)
20
+ )
20
21
  end
21
22
 
22
23
  failure_message_for_should do
23
24
  rescued_exception.message
24
25
  end
26
+
25
27
  end
26
28
 
27
29
  matcher :be_routable do
@@ -63,6 +63,7 @@ module RSpec
63
63
  else
64
64
  model_class = Object.const_set(string_or_model_class, Class.new do
65
65
  extend ActiveModel::Naming
66
+ def self.primary_key; :id; end
66
67
  end)
67
68
  end
68
69
  else
@@ -101,22 +102,27 @@ EOM
101
102
  m.__send__(:__mock_proxy).instance_eval(<<-CODE, __FILE__, __LINE__)
102
103
  def @object.is_a?(other)
103
104
  #{model_class}.ancestors.include?(other)
104
- end
105
+ end unless #{stubs.has_key?(:is_a?)}
106
+
105
107
  def @object.kind_of?(other)
106
108
  #{model_class}.ancestors.include?(other)
107
- end
109
+ end unless #{stubs.has_key?(:kind_of?)}
110
+
108
111
  def @object.instance_of?(other)
109
112
  other == #{model_class}
110
- end
113
+ end unless #{stubs.has_key?(:instance_of?)}
114
+
111
115
  def @object.respond_to?(method_name, include_private=false)
112
116
  #{model_class}.respond_to?(:column_names) && #{model_class}.column_names.include?(method_name.to_s) || super
113
- end
117
+ end unless #{stubs.has_key?(:respond_to?)}
118
+
114
119
  def @object.class
115
120
  #{model_class}
116
- end
121
+ end unless #{stubs.has_key?(:class)}
122
+
117
123
  def @object.to_s
118
124
  "#{model_class.name}_#{to_param}"
119
- end
125
+ end unless #{stubs.has_key?(:to_s)}
120
126
  CODE
121
127
  yield m if block_given?
122
128
  end
@@ -153,7 +159,6 @@ EOM
153
159
  # stub_model(Model)
154
160
  # stub_model(Model).as_new_record
155
161
  # stub_model(Model, hash_of_stubs)
156
- # stub_model(Model, instance_variable_name, hash_of_stubs)
157
162
  #
158
163
  # Creates an instance of +Model+ with +to_param+ stubbed using a
159
164
  # generated value that is unique to each object.. If +Model+ is an
@@ -1,7 +1,7 @@
1
1
  module RSpec # :nodoc:
2
2
  module Rails # :nodoc:
3
3
  module Version # :nodoc:
4
- STRING = '2.6.1'
4
+ STRING = '2.7.0.rc1'
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ # Generators are not automatically loaded by Rails
4
+ require 'generators/rspec/controller/controller_generator'
5
+
6
+ describe Rspec::Generators::ControllerGenerator do
7
+ # Tell the generator where to put its output (what it thinks of as Rails.root)
8
+ destination File.expand_path("../../../../../tmp", __FILE__)
9
+
10
+ before { prepare_destination }
11
+
12
+ describe 'controller specs' do
13
+ subject { file('spec/controllers/posts_controller_spec.rb') }
14
+ describe 'generated by default' do
15
+ before do
16
+ run_generator %w(posts)
17
+ end
18
+
19
+ describe 'the spec' do
20
+ it { should exist }
21
+ it { should contain /require 'spec_helper'/ }
22
+ it { should contain /describe PostsController/ }
23
+ end
24
+ end
25
+ describe 'skipped with a flag' do
26
+ before do
27
+ run_generator %w(posts --no-controller_specs)
28
+ end
29
+ it { should_not exist }
30
+ end
31
+ end
32
+
33
+ describe 'view specs' do
34
+ describe 'are not generated' do
35
+ describe 'with no-view-spec flag' do
36
+ before do
37
+ run_generator %w(posts index show --no-view-specs)
38
+ end
39
+ describe 'index.html.erb' do
40
+ subject { file('spec/views/posts/index.html.erb_spec.rb') }
41
+ it { should_not exist }
42
+ end
43
+ end
44
+ describe 'with no actions' do
45
+ before do
46
+ run_generator %w(posts)
47
+ end
48
+ describe 'index.html.erb' do
49
+ subject { file('spec/views/posts/index.html.erb_spec.rb') }
50
+ it { should_not exist }
51
+ end
52
+ end
53
+ end
54
+
55
+ describe 'are generated' do
56
+ describe 'with default template engine' do
57
+ before do
58
+ run_generator %w(posts index show)
59
+ end
60
+ describe 'index.html.erb' do
61
+ subject { file('spec/views/posts/index.html.erb_spec.rb') }
62
+ it { should exist }
63
+ it { should contain /require 'spec_helper'/ }
64
+ it { should contain /describe "posts\/index.html.erb"/ }
65
+ end
66
+ describe 'show.html.erb' do
67
+ subject { file('spec/views/posts/show.html.erb_spec.rb') }
68
+ it { should exist }
69
+ it { should contain /require 'spec_helper'/ }
70
+ it { should contain /describe "posts\/show.html.erb"/ }
71
+ end
72
+ end
73
+ describe 'with haml' do
74
+ before do
75
+ run_generator %w(posts index --template_engine haml)
76
+ end
77
+ describe 'index.html.haml' do
78
+ subject { file('spec/views/posts/index.html.haml_spec.rb') }
79
+ it { should exist }
80
+ it { should contain /require 'spec_helper'/ }
81
+ it { should contain /describe "posts\/index.html.haml"/ }
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ # Generators are not automatically loaded by Rails
4
+ require 'generators/rspec/helper/helper_generator'
5
+
6
+ describe Rspec::Generators::HelperGenerator do
7
+ # Tell the generator where to put its output (what it thinks of as Rails.root)
8
+ destination File.expand_path("../../../../../tmp", __FILE__)
9
+
10
+ before { prepare_destination }
11
+
12
+ subject { file('spec/helpers/posts_helper_spec.rb') }
13
+ describe 'generated by default' do
14
+ before do
15
+ run_generator %w(posts)
16
+ end
17
+
18
+ describe 'the spec' do
19
+ it { should exist }
20
+ it { should contain /require 'spec_helper'/ }
21
+ it { should contain /describe PostsHelper/ }
22
+ end
23
+ end
24
+ describe 'skipped with a flag' do
25
+ before do
26
+ run_generator %w(posts --no-helper_specs)
27
+ end
28
+ it { should_not exist }
29
+ end
30
+ end