d2059d51f45c2f5ee1b96dab1bd150208224f5a4
[feedcatcher.git] / vendor / rails / actionpack / lib / action_controller / test_case.rb
1 require 'active_support/test_case'
2 require 'action_controller/test_process'
3
4 module ActionController
5 # Superclass for ActionController functional tests. Functional tests allow you to
6 # test a single controller action per test method. This should not be confused with
7 # integration tests (see ActionController::IntegrationTest), which are more like
8 # "stories" that can involve multiple controllers and mutliple actions (i.e. multiple
9 # different HTTP requests).
10 #
11 # == Basic example
12 #
13 # Functional tests are written as follows:
14 # 1. First, one uses the +get+, +post+, +put+, +delete+ or +head+ method to simulate
15 # an HTTP request.
16 # 2. Then, one asserts whether the current state is as expected. "State" can be anything:
17 # the controller's HTTP response, the database contents, etc.
18 #
19 # For example:
20 #
21 # class BooksControllerTest < ActionController::TestCase
22 # def test_create
23 # # Simulate a POST response with the given HTTP parameters.
24 # post(:create, :book => { :title => "Love Hina" })
25 #
26 # # Assert that the controller tried to redirect us to
27 # # the created book's URI.
28 # assert_response :found
29 #
30 # # Assert that the controller really put the book in the database.
31 # assert_not_nil Book.find_by_title("Love Hina")
32 # end
33 # end
34 #
35 # == Special instance variables
36 #
37 # ActionController::TestCase will also automatically provide the following instance
38 # variables for use in the tests:
39 #
40 # <b>@controller</b>::
41 # The controller instance that will be tested.
42 # <b>@request</b>::
43 # An ActionController::TestRequest, representing the current HTTP
44 # request. You can modify this object before sending the HTTP request. For example,
45 # you might want to set some session properties before sending a GET request.
46 # <b>@response</b>::
47 # An ActionController::TestResponse object, representing the response
48 # of the last HTTP response. In the above example, <tt>@response</tt> becomes valid
49 # after calling +post+. If the various assert methods are not sufficient, then you
50 # may use this object to inspect the HTTP response in detail.
51 #
52 # (Earlier versions of Rails required each functional test to subclass
53 # Test::Unit::TestCase and define @controller, @request, @response in +setup+.)
54 #
55 # == Controller is automatically inferred
56 #
57 # ActionController::TestCase will automatically infer the controller under test
58 # from the test class name. If the controller cannot be inferred from the test
59 # class name, you can explicity set it with +tests+.
60 #
61 # class SpecialEdgeCaseWidgetsControllerTest < ActionController::TestCase
62 # tests WidgetController
63 # end
64 #
65 # == Testing controller internals
66 #
67 # In addition to these specific assertions, you also have easy access to various collections that the regular test/unit assertions
68 # can be used against. These collections are:
69 #
70 # * assigns: Instance variables assigned in the action that are available for the view.
71 # * session: Objects being saved in the session.
72 # * flash: The flash objects currently in the session.
73 # * cookies: Cookies being sent to the user on this request.
74 #
75 # These collections can be used just like any other hash:
76 #
77 # assert_not_nil assigns(:person) # makes sure that a @person instance variable was set
78 # assert_equal "Dave", cookies[:name] # makes sure that a cookie called :name was set as "Dave"
79 # assert flash.empty? # makes sure that there's nothing in the flash
80 #
81 # For historic reasons, the assigns hash uses string-based keys. So assigns[:person] won't work, but assigns["person"] will. To
82 # appease our yearning for symbols, though, an alternative accessor has been devised using a method call instead of index referencing.
83 # So assigns(:person) will work just like assigns["person"], but again, assigns[:person] will not work.
84 #
85 # On top of the collections, you have the complete url that a given action redirected to available in redirect_to_url.
86 #
87 # For redirects within the same controller, you can even call follow_redirect and the redirect will be followed, triggering another
88 # action call which can then be asserted against.
89 #
90 # == Manipulating the request collections
91 #
92 # The collections described above link to the response, so you can test if what the actions were expected to do happened. But
93 # sometimes you also want to manipulate these collections in the incoming request. This is really only relevant for sessions
94 # and cookies, though. For sessions, you just do:
95 #
96 # @request.session[:key] = "value"
97 # @request.cookies["key"] = "value"
98 #
99 # == Testing named routes
100 #
101 # If you're using named routes, they can be easily tested using the original named routes' methods straight in the test case.
102 # Example:
103 #
104 # assert_redirected_to page_url(:title => 'foo')
105 class TestCase < ActiveSupport::TestCase
106 include TestProcess
107
108 module Assertions
109 %w(response selector tag dom routing model).each do |kind|
110 include ActionController::Assertions.const_get("#{kind.camelize}Assertions")
111 end
112
113 def clean_backtrace(&block)
114 yield
115 rescue ActiveSupport::TestCase::Assertion => error
116 framework_path = Regexp.new(File.expand_path("#{File.dirname(__FILE__)}/assertions"))
117 error.backtrace.reject! { |line| File.expand_path(line) =~ framework_path }
118 raise
119 end
120 end
121 include Assertions
122
123 # When the request.remote_addr remains the default for testing, which is 0.0.0.0, the exception is simply raised inline
124 # (bystepping the regular exception handling from rescue_action). If the request.remote_addr is anything else, the regular
125 # rescue_action process takes place. This means you can test your rescue_action code by setting remote_addr to something else
126 # than 0.0.0.0.
127 #
128 # The exception is stored in the exception accessor for further inspection.
129 module RaiseActionExceptions
130 def self.included(base)
131 base.class_eval do
132 attr_accessor :exception
133 protected :exception, :exception=
134 end
135 end
136
137 protected
138 def rescue_action_without_handler(e)
139 self.exception = e
140
141 if request.remote_addr == "0.0.0.0"
142 raise(e)
143 else
144 super(e)
145 end
146 end
147 end
148
149 setup :setup_controller_request_and_response
150
151 @@controller_class = nil
152
153 class << self
154 # Sets the controller class name. Useful if the name can't be inferred from test class.
155 # Expects +controller_class+ as a constant. Example: <tt>tests WidgetController</tt>.
156 def tests(controller_class)
157 self.controller_class = controller_class
158 end
159
160 def controller_class=(new_class)
161 prepare_controller_class(new_class) if new_class
162 write_inheritable_attribute(:controller_class, new_class)
163 end
164
165 def controller_class
166 if current_controller_class = read_inheritable_attribute(:controller_class)
167 current_controller_class
168 else
169 self.controller_class = determine_default_controller_class(name)
170 end
171 end
172
173 def determine_default_controller_class(name)
174 name.sub(/Test$/, '').constantize
175 rescue NameError
176 nil
177 end
178
179 def prepare_controller_class(new_class)
180 new_class.send :include, RaiseActionExceptions
181 end
182 end
183
184 def setup_controller_request_and_response
185 @request = TestRequest.new
186 @response = TestResponse.new
187
188 if klass = self.class.controller_class
189 @controller ||= klass.new rescue nil
190 end
191
192 if @controller
193 @controller.request = @request
194 @controller.params = {}
195 @controller.send(:initialize_current_url)
196 end
197 end
198
199 # Cause the action to be rescued according to the regular rules for rescue_action when the visitor is not local
200 def rescue_action_in_public!
201 @request.remote_addr = '208.77.188.166' # example.com
202 end
203 end
204 end