rspec-rails 2.0.0.beta.19 → 2.0.0.beta.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/.gitignore +2 -1
  2. data/Gemfile +7 -0
  3. data/Gotchas.markdown +14 -0
  4. data/README.markdown +49 -9
  5. data/Rakefile +1 -2
  6. data/Upgrade.markdown +7 -0
  7. data/VERSION +1 -1
  8. data/features/controller_specs/anonymous_controller.feature +57 -19
  9. data/features/controller_specs/isolation_from_views.feature +2 -2
  10. data/features/controller_specs/readers.feature +1 -1
  11. data/features/controller_specs/render_views.feature +4 -4
  12. data/features/helper_specs/helper_spec.feature +53 -0
  13. data/features/mailer_specs/url_helpers.feature +2 -2
  14. data/features/matchers/new_record_matcher.feature +46 -1
  15. data/features/matchers/redirect_to_matcher.feature +41 -0
  16. data/features/matchers/render_template_matcher.feature +25 -0
  17. data/features/mocks/mock_model.feature +131 -0
  18. data/features/mocks/stub_model.feature +58 -0
  19. data/features/routing_specs/access_to_named_routes.feature +15 -0
  20. data/features/support/env.rb +1 -0
  21. data/features/view_specs/inferred_controller_path.feature +44 -0
  22. data/lib/generators/rspec/install/templates/spec/spec_helper.rb +4 -5
  23. data/lib/generators/rspec/scaffold/templates/routing_spec.rb +2 -2
  24. data/lib/rspec/rails.rb +1 -4
  25. data/lib/rspec/rails/adapters.rb +32 -6
  26. data/lib/rspec/rails/browser_simulators.rb +30 -0
  27. data/lib/rspec/rails/example.rb +2 -1
  28. data/lib/rspec/rails/example/controller_example_group.rb +36 -16
  29. data/lib/rspec/rails/example/helper_example_group.rb +8 -4
  30. data/lib/rspec/rails/example/mailer_example_group.rb +11 -2
  31. data/lib/rspec/rails/example/model_example_group.rb +1 -1
  32. data/lib/rspec/rails/example/rails_example_group.rb +11 -0
  33. data/lib/rspec/rails/example/request_example_group.rb +17 -6
  34. data/lib/rspec/rails/example/routing_example_group.rb +6 -1
  35. data/lib/rspec/rails/example/view_example_group.rb +18 -14
  36. data/lib/rspec/rails/matchers/be_a_new.rb +36 -1
  37. data/lib/rspec/rails/mocks.rb +9 -8
  38. data/lib/rspec/rails/tasks/rspec.rake +7 -0
  39. data/lib/rspec/rails/view_rendering.rb +8 -2
  40. data/rspec-rails.gemspec +21 -14
  41. data/spec/rspec/rails/assertion_adapter_spec.rb +28 -0
  42. data/spec/rspec/rails/example/helper_example_group_spec.rb +2 -0
  43. data/spec/rspec/rails/example/routing_example_group_spec.rb +17 -0
  44. data/spec/rspec/rails/example/view_rendering_spec.rb +56 -15
  45. data/spec/rspec/rails/matchers/be_a_new_spec.rb +98 -0
  46. data/spec/rspec/rails/matchers/errors_on_spec.rb +4 -4
  47. data/spec/rspec/rails/mocks/ar_classes.rb +17 -0
  48. data/spec/rspec/rails/mocks/stub_model_spec.rb +36 -15
  49. data/templates/Gemfile +2 -0
  50. metadata +23 -34
  51. data/lib/rspec/rails/monkey.rb +0 -1
  52. data/lib/rspec/rails/monkey/action_mailer/test_case.rb +0 -69
@@ -0,0 +1,41 @@
1
+ Feature: redirect_to matcher
2
+
3
+ The redirect_to matcher is used to specify that the redirect called
4
+ in the latest action ended with the intended behaviour. Essentially,
5
+ it delegates to "assert_redirect". For more info, please check out
6
+ the Rails documentation on this method.
7
+
8
+ It is available in controller specs (spec/controllers) and request
9
+ specs (spec/requests).
10
+
11
+ Scenario: redirect_to with four possible options
12
+ Given a file named "spec/controllers/widgets_controller_spec.rb" with:
13
+ """
14
+ require "spec_helper"
15
+
16
+ describe WidgetsController do
17
+
18
+ describe "#create" do
19
+ subject { post :create, :widget => { :name => "Foo" } }
20
+
21
+ it "redirects to widget_url(@widget)" do
22
+ subject.should redirect_to(widget_url(assigns(:widget)))
23
+ end
24
+
25
+ it "redirects_to :action => :show" do
26
+ subject.should redirect_to :action => :show,
27
+ :id => assigns(:widget).id
28
+ end
29
+
30
+ it "redirects_to(@widget)" do
31
+ subject.should redirect_to(assigns(:widget))
32
+ end
33
+
34
+ it "redirects_to /widgets/:id" do
35
+ subject.should redirect_to("/widgets/#{assigns(:widget).id}")
36
+ end
37
+ end
38
+ end
39
+ """
40
+ When I run "rspec spec/controllers/widgets_controller_spec.rb"
41
+ Then the output should contain "4 examples, 0 failures"
@@ -0,0 +1,25 @@
1
+ Feature: render_template matcher
2
+
3
+ This matcher just delegates to the Rails assertion method
4
+ "assert_template". For complete info on the available options,
5
+ please take a look at the Rails documentation.
6
+
7
+ This method is available in spec/controllers and spec/requests.
8
+
9
+ Scenario: render_template with three possible options
10
+ Given a file named "spec/controllers/gadgets_spec.rb" with:
11
+ """
12
+ require "spec_helper"
13
+
14
+ describe GadgetsController do
15
+ describe "#index" do
16
+ subject { get :index }
17
+
18
+ specify { should render_template(:index) }
19
+ specify { should render_template("index") }
20
+ specify { should render_template("gadgets/index") }
21
+ end
22
+ end
23
+ """
24
+ When I run "rspec spec/controllers/gadgets_spec.rb"
25
+ Then the output should contain "3 examples, 0 failures"
@@ -0,0 +1,131 @@
1
+ Feature: mock_model
2
+
3
+ The mock_model method generates a test double object that acts like an
4
+ Active Model model. This is different from the stub_model method which
5
+ generates an instance of a real ActiveModel class.
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
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
11
+ generated object will act as though its an instance of the class named by
12
+ that string.
13
+
14
+ Scenario: passing a string that represents a non-existent constant
15
+ Given a file named "spec/models/car_spec.rb" with:
16
+ """
17
+ require "spec_helper"
18
+
19
+ describe "mock_model('Car') with no Car constant in existence" do
20
+ it "generates a constant" do
21
+ Object.const_defined?(:Car).should be_false
22
+ mock_model("Car")
23
+ Object.const_defined?(:Car).should be_true
24
+ end
25
+
26
+ describe "generates an object that ..." do
27
+ it "returns the correct name" do
28
+ car = mock_model("Car")
29
+ car.class.name.should eq("Car")
30
+ end
31
+
32
+ it "says it is a Car" do
33
+ car = mock_model("Car")
34
+ car.should be_a(Car)
35
+ end
36
+ end
37
+ end
38
+ """
39
+ When I run "rspec spec/models/car_spec.rb"
40
+ Then the output should contain "3 examples, 0 failures"
41
+
42
+ Scenario: passing a string that represents an existing constant
43
+ Given a file named "spec/models/widget_spec.rb" with:
44
+ """
45
+ require "spec_helper"
46
+
47
+ describe Widget do
48
+ it "uses the existing constant" do
49
+ widget = mock_model("Widget")
50
+ widget.should be_a(Widget)
51
+ end
52
+ end
53
+ """
54
+ When I run "rspec spec/models/widget_spec.rb"
55
+ Then the output should contain "1 example, 0 failures"
56
+
57
+ Scenario: passing a class that does not extend ActiveModel::Naming
58
+ Given a file named "spec/models/string_spec.rb" with:
59
+ """
60
+ require "spec_helper"
61
+
62
+ describe String do
63
+ it "raises" do
64
+ expect { mock_model(String) }.to raise_exception
65
+ end
66
+ end
67
+ """
68
+ When I run "rspec spec/models/string_spec.rb"
69
+ Then the output should contain "1 example, 0 failures"
70
+
71
+ Scenario: passing an Active Record constant
72
+ Given a file named "spec/models/widget_spec.rb" with:
73
+ """
74
+ require "spec_helper"
75
+
76
+ describe Widget do
77
+ let(:widget) { mock_model(Widget) }
78
+
79
+ it "is valid by default" do
80
+ widget.should be_valid
81
+ end
82
+
83
+ it "is not a new record by default" do
84
+ widget.should_not be_new_record
85
+ end
86
+
87
+ it "can be converted to a new record" do
88
+ widget.as_new_record.should be_new_record
89
+ end
90
+
91
+ it "sets :id to nil upon destroy" do
92
+ widget.destroy
93
+ widget.id.should be_nil
94
+ end
95
+ end
96
+ """
97
+ When I run "rspec spec/models/widget_spec.rb"
98
+ Then the output should contain "4 examples, 0 failures"
99
+
100
+ Scenario: passing an Active Record constant with method stubs
101
+ Given a file named "spec/models/widget_spec.rb" with:
102
+ """
103
+ require "spec_helper"
104
+
105
+ describe "mock_model(Widget) with stubs" do
106
+ let(:widget) do
107
+ mock_model Widget, :foo => "bar",
108
+ :save => true,
109
+ :update_attributes => false
110
+ end
111
+
112
+ it "supports stubs for methods that don't exist in ActiveModel or ActiveRecord" do
113
+ widget.foo.should eq("bar")
114
+ end
115
+
116
+ it "supports stubs for methods that do exist" do
117
+ widget.save.should eq(true)
118
+ widget.update_attributes.should be_false
119
+ end
120
+
121
+ describe "#errors" do
122
+ context "with update_attributes => false" do
123
+ it "is not empty" do
124
+ widget.errors.should_not be_empty
125
+ end
126
+ end
127
+ end
128
+ end
129
+ """
130
+ When I run "rspec spec/models/widget_spec.rb"
131
+ Then the output should contain "3 examples, 0 failures"
@@ -0,0 +1,58 @@
1
+ Feature: stub_model
2
+
3
+ The stub_model method generates an instance of a Active Model model.
4
+
5
+ While you can use stub_model in any example (model, view, controller,
6
+ helper), it is especially useful in view examples, which are inherently
7
+ more state-based than interaction-based.
8
+
9
+ Scenario: passing an Active Record constant with a hash of stubs
10
+ Given a file named "spec/models/widget_spec.rb" with:
11
+ """
12
+ require "spec_helper"
13
+
14
+ describe "stub_model(Widget) with a hash of stubs" do
15
+ let(:widget) do
16
+ stub_model Widget, :id => 5, :random_attribute => true
17
+ end
18
+
19
+ it "stubs :id" do
20
+ widget.id.should eql(5)
21
+ end
22
+
23
+ it "stubs :random_attribute" do
24
+ widget.random_attribute.should be_true
25
+ end
26
+
27
+ it "returns false for new_record? if :id is set" do
28
+ widget.should_not be_new_record
29
+ end
30
+
31
+ it "can be converted to a new record" do
32
+ widget.as_new_record
33
+ widget.should be_new_record
34
+ end
35
+ end
36
+ """
37
+ When I run "rspec spec/models/widget_spec.rb"
38
+ Then the output should contain "4 examples, 0 failures"
39
+
40
+ Scenario: passing an Active Record constant with a block of stubs
41
+ Given a file named "spec/models/widget_spec.rb" with:
42
+ """
43
+ require "spec_helper"
44
+
45
+ describe "stub_model(Widget) with a block of stubs" do
46
+ let(:widget) do
47
+ stub_model Widget do |widget|
48
+ widget.id = 5
49
+ end
50
+ end
51
+
52
+ it "stubs :id" do
53
+ widget.id.should eql(5)
54
+ end
55
+ end
56
+ """
57
+ When I run "rspec spec/models/widget_spec.rb"
58
+ Then the output should contain "1 example, 0 failures"
@@ -0,0 +1,15 @@
1
+ Feature: access to named routes in routing specs
2
+
3
+ Scenario: access existing named route
4
+ Given a file named "spec/routing/widget_routes_spec.rb" with:
5
+ """
6
+ require "spec_helper"
7
+
8
+ describe "routes to the widgets controller" do
9
+ it "routes a named route" do
10
+ {:get => new_widget_path}.should route_to(:controller => "widgets", :action => "new")
11
+ end
12
+ end
13
+ """
14
+ When I run "rspec spec"
15
+ Then the output should contain "1 example, 0 failures"
@@ -1,4 +1,5 @@
1
1
  require 'aruba'
2
+ require 'webrat'
2
3
 
3
4
  unless File.directory?('./tmp/example_app')
4
5
  system "rake generate:app generate:stuff"
@@ -0,0 +1,44 @@
1
+ Feature: view spec infers controller path and action
2
+
3
+ Scenario: infer controller path
4
+ Given a file named "spec/views/widgets/new.html.erb_spec.rb" with:
5
+ """
6
+ require "spec_helper"
7
+
8
+ describe "widgets/new.html.erb" do
9
+ it "infers the controller path" do
10
+ controller.request.path_parameters["controller"].should eq("widgets")
11
+ end
12
+ end
13
+ """
14
+ When I run "rspec spec/views"
15
+ Then the output should contain "1 example, 0 failures"
16
+
17
+ Scenario: infer action
18
+ Given a file named "spec/views/widgets/new.html.erb_spec.rb" with:
19
+ """
20
+ require "spec_helper"
21
+
22
+ describe "widgets/new.html.erb" do
23
+ it "infers the controller path" do
24
+ controller.request.path_parameters["action"].should eq("new")
25
+ end
26
+ end
27
+ """
28
+ When I run "rspec spec/views"
29
+ Then the output should contain "1 example, 0 failures"
30
+
31
+ Scenario: do not infer action in a partial
32
+ Given a file named "spec/views/widgets/_form.html.erb_spec.rb" with:
33
+ """
34
+ require "spec_helper"
35
+
36
+ describe "widgets/_form.html.erb" do
37
+ it "includes a link to new" do
38
+ controller.request.path_parameters["action"].should be_nil
39
+ end
40
+ end
41
+ """
42
+ When I run "rspec spec/views"
43
+ Then the output should contain "1 example, 0 failures"
44
+
@@ -1,12 +1,11 @@
1
- # This file is copied to ~/spec when you run 'ruby script/generate rspec'
2
- # from the project root directory.
1
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
3
2
  ENV["RAILS_ENV"] ||= 'test'
4
3
  require File.expand_path("../../config/environment", __FILE__)
5
4
  require 'rspec/rails'
6
5
 
7
- # Requires supporting files with custom matchers and macros, etc,
8
- # in ./support/ and its subdirectories.
9
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
6
+ # Requires supporting ruby files with custom matchers and macros, etc,
7
+ # in spec/support/ and its subdirectories.
8
+ Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
10
9
 
11
10
  RSpec.configure do |config|
12
11
  # == Mock Framework
@@ -3,12 +3,12 @@ require "spec_helper"
3
3
  describe <%= controller_class_name %>Controller do
4
4
  describe "routing" do
5
5
 
6
- <% unless options[:singleton] -%>
6
+ <% unless options[:singleton] -%>
7
7
  it "recognizes and generates #index" do
8
8
  { :get => "/<%= table_name %>" }.should route_to(:controller => "<%= table_name %>", :action => "index")
9
9
  end
10
10
 
11
- <% end -%>
11
+ <% end -%>
12
12
  it "recognizes and generates #new" do
13
13
  { :get => "/<%= table_name %>/new" }.should route_to(:controller => "<%= table_name %>", :action => "new")
14
14
  end
@@ -1,7 +1,4 @@
1
- require 'webrat'
2
-
3
1
  require 'rspec/core'
4
- require 'rspec/rails/monkey'
5
2
  require 'rspec/rails/extensions'
6
3
  require 'rspec/rails/view_rendering'
7
4
  require 'rspec/rails/adapters'
@@ -9,5 +6,5 @@ require 'rspec/rails/matchers'
9
6
  require 'rspec/rails/fixture_support'
10
7
  require 'rspec/rails/mocks'
11
8
  require 'rspec/rails/module_inclusion'
9
+ require 'rspec/rails/browser_simulators'
12
10
  require 'rspec/rails/example'
13
-
@@ -15,21 +15,47 @@ module RSpec
15
15
  methods.each {|method| after { send method } }
16
16
  end
17
17
  end
18
+
19
+ module InstanceMethods
20
+ def method_name
21
+ @example
22
+ end
23
+ end
18
24
  end
19
25
 
20
26
  module TestUnitAssertionAdapter
21
27
  extend ActiveSupport::Concern
22
- def method_name
23
- @example
28
+
29
+ class AssertionDelegate
30
+ include Test::Unit::Assertions
24
31
  end
25
32
 
26
- include Test::Unit::Assertions
33
+ module ClassMethods
34
+ def assertion_method_names
35
+ Test::Unit::Assertions.public_instance_methods.select{|m| m.to_s =~ /^assert/} +
36
+ [:build_message]
37
+ end
27
38
 
28
- included do
29
- before do
30
- @_result = Struct.new(:add_assertion).new
39
+ def define_assertion_delegators
40
+ assertion_method_names.each do |m|
41
+ class_eval <<-CODE
42
+ def #{m}(*args, &block)
43
+ assertion_delegate.send :#{m}, *args, &block
44
+ end
45
+ CODE
46
+ end
31
47
  end
32
48
  end
49
+
50
+ module InstanceMethods
51
+ def assertion_delegate
52
+ @assertion_delegate ||= AssertionDelegate.new
53
+ end
54
+ end
55
+
56
+ included do
57
+ define_assertion_delegators
58
+ end
33
59
  end
34
60
  end
35
61
  end
@@ -0,0 +1,30 @@
1
+ begin
2
+ require 'capybara/rails'
3
+ rescue LoadError
4
+ end
5
+
6
+ begin
7
+ require 'webrat'
8
+ rescue LoadError
9
+ end
10
+
11
+ module RSpec
12
+ module Rails
13
+ module BrowserSimulators
14
+ extend ActiveSupport::Concern
15
+
16
+ def self.included(mod)
17
+ mod.instance_eval do
18
+ def webrat(&block)
19
+ block.call if defined?(Webrat)
20
+ end
21
+
22
+ def capybara(&block)
23
+ block.call if defined?(Capybara)
24
+ end
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end