4fc60f069784a5a72a1d691634d4f19cfcf4edb5
[depot.git] / test_case.rb
1 require 'active_support/test_case'
2
3 module ActionController
4 class NonInferrableControllerError < ActionControllerError
5 def initialize(name)
6 @name = name
7 super "Unable to determine the controller to test from #{name}. " +
8 "You'll need to specify it using 'tests YourController' in your " +
9 "test case definition. This could mean that #{inferred_controller_name} does not exist " +
10 "or it contains syntax errors"
11 end
12
13 def inferred_controller_name
14 @name.sub(/Test$/, '')
15 end
16 end
17
18 # Superclass for ActionController functional tests. Functional tests allow you to
19 # test a single controller action per test method. This should not be confused with
20 # integration tests (see ActionController::IntegrationTest), which are more like
21 # "stories" that can involve multiple controllers and mutliple actions (i.e. multiple
22 # different HTTP requests).
23 #
24 # == Basic example
25 #
26 # Functional tests are written as follows:
27 # 1. First, one uses the +get+, +post+, +put+, +delete+ or +head+ method to simulate
28 # an HTTP request.
29 # 2. Then, one asserts whether the current state is as expected. "State" can be anything:
30 # the controller's HTTP response, the database contents, etc.
31 #
32 # For example:
33 #
34 # class BooksControllerTest < ActionController::TestCase
35 # def test_create
36 # # Simulate a POST response with the given HTTP parameters.
37 # post(:create, :book => { :title => "Love Hina" })
38 #
39 # # Assert that the controller tried to redirect us to
40 # # the created book's URI.
41 # assert_response :found
42 #
43 # # Assert that the controller really put the book in the database.
44 # assert_not_nil Book.find_by_title("Love Hina")
45 # end
46 # end
47 #
48 # == Special instance variables
49 #
50 # ActionController::TestCase will also automatically provide the following instance
51 # variables for use in the tests:
52 #
53 # <b>@controller</b>::
54 # The controller instance that will be tested.
55 # <b>@request</b>::
56 # An ActionController::TestRequest, representing the current HTTP
57 # request. You can modify this object before sending the HTTP request. For example,
58 # you might want to set some session properties before sending a GET request.
59 # <b>@response</b>::
60 # An ActionController::TestResponse object, representing the response
61 # of the last HTTP response. In the above example, <tt>@response</tt> becomes valid
62 # after calling +post+. If the various assert methods are not sufficient, then you
63 # may use this object to inspect the HTTP response in detail.
64 #
65 # (Earlier versions of Rails required each functional test to subclass
66 # Test::Unit::TestCase and define @controller, @request, @response in +setup+.)
67 #
68 # == Controller is automatically inferred
69 #
70 # ActionController::TestCase will automatically infer the controller under test
71 # from the test class name. If the controller cannot be inferred from the test
72 # class name, you can explicity set it with +tests+.
73 #
74 # class SpecialEdgeCaseWidgetsControllerTest < ActionController::TestCase
75 # tests WidgetController
76 # end
77 class TestCase < ActiveSupport::TestCase
78 # When the request.remote_addr remains the default for testing, which is 0.0.0.0, the exception is simply raised inline
79 # (bystepping the regular exception handling from rescue_action). If the request.remote_addr is anything else, the regular
80 # rescue_action process takes place. This means you can test your rescue_action code by setting remote_addr to something else
81 # than 0.0.0.0.
82 #
83 # The exception is stored in the exception accessor for further inspection.
84 module RaiseActionExceptions
85 attr_accessor :exception
86
87 def rescue_action_without_handler(e)
88 self.exception = e
89
90 if request.remote_addr == "0.0.0.0"
91 raise(e)
92 else
93 super(e)
94 end
95 end
96 end
97
98 setup :setup_controller_request_and_response
99
100 @@controller_class = nil
101
102 class << self
103 # Sets the controller class name. Useful if the name can't be inferred from test class.
104 # Expects +controller_class+ as a constant. Example: <tt>tests WidgetController</tt>.
105 def tests(controller_class)
106 self.controller_class = controller_class
107 end
108
109 def controller_class=(new_class)
110 prepare_controller_class(new_class)
111 write_inheritable_attribute(:controller_class, new_class)
112 end
113
114 def controller_class
115 if current_controller_class = read_inheritable_attribute(:controller_class)
116 current_controller_class
117 else
118 self.controller_class = determine_default_controller_class(name)
119 end
120 end
121
122 def determine_default_controller_class(name)
123 name.sub(/Test$/, '').constantize
124 rescue NameError
125 raise NonInferrableControllerError.new(name)
126 end
127
128 def prepare_controller_class(new_class)
129 new_class.send :include, RaiseActionExceptions
130 end
131 end
132
133 def setup_controller_request_and_response
134 @controller = self.class.controller_class.new
135 @controller.request = @request = TestRequest.new
136 @response = TestResponse.new
137
138 @controller.params = {}
139 @controller.send(:initialize_current_url)
140 end
141
142 # Cause the action to be rescued according to the regular rules for rescue_action when the visitor is not local
143 def rescue_action_in_public!
144 @request.remote_addr = '208.77.188.166' # example.com
145 end
146 end
147 end