##// END OF EJS Templates
Ruby 1.9: fix tests error due to require path at test/test_helper.rb...
Toshi MARUYAMA -
r7682:c54b33ddca34
parent child
Show More
@@ -1,448 +1,448
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 ENV["RAILS_ENV"] = "test"
18 ENV["RAILS_ENV"] = "test"
19 require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
19 require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
20 require 'test_help'
20 require 'test_help'
21 require File.expand_path(File.dirname(__FILE__) + '/helper_testcase')
21 require File.expand_path(File.dirname(__FILE__) + '/helper_testcase')
22 require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb')
22 require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
23
23
24 require File.expand_path(File.dirname(__FILE__) + '/object_daddy_helpers')
24 require File.expand_path(File.dirname(__FILE__) + '/object_daddy_helpers')
25 include ObjectDaddyHelpers
25 include ObjectDaddyHelpers
26
26
27 class ActiveSupport::TestCase
27 class ActiveSupport::TestCase
28 # Transactional fixtures accelerate your tests by wrapping each test method
28 # Transactional fixtures accelerate your tests by wrapping each test method
29 # in a transaction that's rolled back on completion. This ensures that the
29 # in a transaction that's rolled back on completion. This ensures that the
30 # test database remains unchanged so your fixtures don't have to be reloaded
30 # test database remains unchanged so your fixtures don't have to be reloaded
31 # between every test method. Fewer database queries means faster tests.
31 # between every test method. Fewer database queries means faster tests.
32 #
32 #
33 # Read Mike Clark's excellent walkthrough at
33 # Read Mike Clark's excellent walkthrough at
34 # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
34 # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
35 #
35 #
36 # Every Active Record database supports transactions except MyISAM tables
36 # Every Active Record database supports transactions except MyISAM tables
37 # in MySQL. Turn off transactional fixtures in this case; however, if you
37 # in MySQL. Turn off transactional fixtures in this case; however, if you
38 # don't care one way or the other, switching from MyISAM to InnoDB tables
38 # don't care one way or the other, switching from MyISAM to InnoDB tables
39 # is recommended.
39 # is recommended.
40 self.use_transactional_fixtures = true
40 self.use_transactional_fixtures = true
41
41
42 # Instantiated fixtures are slow, but give you @david where otherwise you
42 # Instantiated fixtures are slow, but give you @david where otherwise you
43 # would need people(:david). If you don't want to migrate your existing
43 # would need people(:david). If you don't want to migrate your existing
44 # test cases which use the @david style and don't mind the speed hit (each
44 # test cases which use the @david style and don't mind the speed hit (each
45 # instantiated fixtures translates to a database query per test method),
45 # instantiated fixtures translates to a database query per test method),
46 # then set this back to true.
46 # then set this back to true.
47 self.use_instantiated_fixtures = false
47 self.use_instantiated_fixtures = false
48
48
49 # Add more helper methods to be used by all tests here...
49 # Add more helper methods to be used by all tests here...
50
50
51 def log_user(login, password)
51 def log_user(login, password)
52 User.anonymous
52 User.anonymous
53 get "/login"
53 get "/login"
54 assert_equal nil, session[:user_id]
54 assert_equal nil, session[:user_id]
55 assert_response :success
55 assert_response :success
56 assert_template "account/login"
56 assert_template "account/login"
57 post "/login", :username => login, :password => password
57 post "/login", :username => login, :password => password
58 assert_equal login, User.find(session[:user_id]).login
58 assert_equal login, User.find(session[:user_id]).login
59 end
59 end
60
60
61 def uploaded_test_file(name, mime)
61 def uploaded_test_file(name, mime)
62 ActionController::TestUploadedFile.new(ActiveSupport::TestCase.fixture_path + "/files/#{name}", mime, true)
62 ActionController::TestUploadedFile.new(ActiveSupport::TestCase.fixture_path + "/files/#{name}", mime, true)
63 end
63 end
64
64
65 # Mock out a file
65 # Mock out a file
66 def self.mock_file
66 def self.mock_file
67 file = 'a_file.png'
67 file = 'a_file.png'
68 file.stubs(:size).returns(32)
68 file.stubs(:size).returns(32)
69 file.stubs(:original_filename).returns('a_file.png')
69 file.stubs(:original_filename).returns('a_file.png')
70 file.stubs(:content_type).returns('image/png')
70 file.stubs(:content_type).returns('image/png')
71 file.stubs(:read).returns(false)
71 file.stubs(:read).returns(false)
72 file
72 file
73 end
73 end
74
74
75 def mock_file
75 def mock_file
76 self.class.mock_file
76 self.class.mock_file
77 end
77 end
78
78
79 # Use a temporary directory for attachment related tests
79 # Use a temporary directory for attachment related tests
80 def set_tmp_attachments_directory
80 def set_tmp_attachments_directory
81 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
81 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
82 unless File.directory?("#{Rails.root}/tmp/test/attachments")
82 unless File.directory?("#{Rails.root}/tmp/test/attachments")
83 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
83 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
84 end
84 end
85 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
85 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
86 end
86 end
87
87
88 def with_settings(options, &block)
88 def with_settings(options, &block)
89 saved_settings = options.keys.inject({}) {|h, k| h[k] = Setting[k].dup; h}
89 saved_settings = options.keys.inject({}) {|h, k| h[k] = Setting[k].dup; h}
90 options.each {|k, v| Setting[k] = v}
90 options.each {|k, v| Setting[k] = v}
91 yield
91 yield
92 ensure
92 ensure
93 saved_settings.each {|k, v| Setting[k] = v}
93 saved_settings.each {|k, v| Setting[k] = v}
94 end
94 end
95
95
96 def change_user_password(login, new_password)
96 def change_user_password(login, new_password)
97 user = User.first(:conditions => {:login => login})
97 user = User.first(:conditions => {:login => login})
98 user.password, user.password_confirmation = new_password, new_password
98 user.password, user.password_confirmation = new_password, new_password
99 user.save!
99 user.save!
100 end
100 end
101
101
102 def self.ldap_configured?
102 def self.ldap_configured?
103 @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
103 @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
104 return @test_ldap.bind
104 return @test_ldap.bind
105 rescue Exception => e
105 rescue Exception => e
106 # LDAP is not listening
106 # LDAP is not listening
107 return nil
107 return nil
108 end
108 end
109
109
110 # Returns the path to the test +vendor+ repository
110 # Returns the path to the test +vendor+ repository
111 def self.repository_path(vendor)
111 def self.repository_path(vendor)
112 Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
112 Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
113 end
113 end
114
114
115 # Returns the url of the subversion test repository
115 # Returns the url of the subversion test repository
116 def self.subversion_repository_url
116 def self.subversion_repository_url
117 path = repository_path('subversion')
117 path = repository_path('subversion')
118 path = '/' + path unless path.starts_with?('/')
118 path = '/' + path unless path.starts_with?('/')
119 "file://#{path}"
119 "file://#{path}"
120 end
120 end
121
121
122 # Returns true if the +vendor+ test repository is configured
122 # Returns true if the +vendor+ test repository is configured
123 def self.repository_configured?(vendor)
123 def self.repository_configured?(vendor)
124 File.directory?(repository_path(vendor))
124 File.directory?(repository_path(vendor))
125 end
125 end
126
126
127 def assert_error_tag(options={})
127 def assert_error_tag(options={})
128 assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options))
128 assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options))
129 end
129 end
130
130
131 def assert_include(expected, s)
131 def assert_include(expected, s)
132 assert s.include?(expected), "\"#{expected}\" not found in \"#{s}\""
132 assert s.include?(expected), "\"#{expected}\" not found in \"#{s}\""
133 end
133 end
134
134
135 # Shoulda macros
135 # Shoulda macros
136 def self.should_render_404
136 def self.should_render_404
137 should_respond_with :not_found
137 should_respond_with :not_found
138 should_render_template 'common/error'
138 should_render_template 'common/error'
139 end
139 end
140
140
141 def self.should_have_before_filter(expected_method, options = {})
141 def self.should_have_before_filter(expected_method, options = {})
142 should_have_filter('before', expected_method, options)
142 should_have_filter('before', expected_method, options)
143 end
143 end
144
144
145 def self.should_have_after_filter(expected_method, options = {})
145 def self.should_have_after_filter(expected_method, options = {})
146 should_have_filter('after', expected_method, options)
146 should_have_filter('after', expected_method, options)
147 end
147 end
148
148
149 def self.should_have_filter(filter_type, expected_method, options)
149 def self.should_have_filter(filter_type, expected_method, options)
150 description = "have #{filter_type}_filter :#{expected_method}"
150 description = "have #{filter_type}_filter :#{expected_method}"
151 description << " with #{options.inspect}" unless options.empty?
151 description << " with #{options.inspect}" unless options.empty?
152
152
153 should description do
153 should description do
154 klass = "action_controller/filters/#{filter_type}_filter".classify.constantize
154 klass = "action_controller/filters/#{filter_type}_filter".classify.constantize
155 expected = klass.new(:filter, expected_method.to_sym, options)
155 expected = klass.new(:filter, expected_method.to_sym, options)
156 assert_equal 1, @controller.class.filter_chain.select { |filter|
156 assert_equal 1, @controller.class.filter_chain.select { |filter|
157 filter.method == expected.method && filter.kind == expected.kind &&
157 filter.method == expected.method && filter.kind == expected.kind &&
158 filter.options == expected.options && filter.class == expected.class
158 filter.options == expected.options && filter.class == expected.class
159 }.size
159 }.size
160 end
160 end
161 end
161 end
162
162
163 def self.should_show_the_old_and_new_values_for(prop_key, model, &block)
163 def self.should_show_the_old_and_new_values_for(prop_key, model, &block)
164 context "" do
164 context "" do
165 setup do
165 setup do
166 if block_given?
166 if block_given?
167 instance_eval &block
167 instance_eval &block
168 else
168 else
169 @old_value = model.generate!
169 @old_value = model.generate!
170 @new_value = model.generate!
170 @new_value = model.generate!
171 end
171 end
172 end
172 end
173
173
174 should "use the new value's name" do
174 should "use the new value's name" do
175 @detail = JournalDetail.generate!(:property => 'attr',
175 @detail = JournalDetail.generate!(:property => 'attr',
176 :old_value => @old_value.id,
176 :old_value => @old_value.id,
177 :value => @new_value.id,
177 :value => @new_value.id,
178 :prop_key => prop_key)
178 :prop_key => prop_key)
179
179
180 assert_match @new_value.name, show_detail(@detail, true)
180 assert_match @new_value.name, show_detail(@detail, true)
181 end
181 end
182
182
183 should "use the old value's name" do
183 should "use the old value's name" do
184 @detail = JournalDetail.generate!(:property => 'attr',
184 @detail = JournalDetail.generate!(:property => 'attr',
185 :old_value => @old_value.id,
185 :old_value => @old_value.id,
186 :value => @new_value.id,
186 :value => @new_value.id,
187 :prop_key => prop_key)
187 :prop_key => prop_key)
188
188
189 assert_match @old_value.name, show_detail(@detail, true)
189 assert_match @old_value.name, show_detail(@detail, true)
190 end
190 end
191 end
191 end
192 end
192 end
193
193
194 def self.should_create_a_new_user(&block)
194 def self.should_create_a_new_user(&block)
195 should "create a new user" do
195 should "create a new user" do
196 user = instance_eval &block
196 user = instance_eval &block
197 assert user
197 assert user
198 assert_kind_of User, user
198 assert_kind_of User, user
199 assert !user.new_record?
199 assert !user.new_record?
200 end
200 end
201 end
201 end
202
202
203 # Test that a request allows the three types of API authentication
203 # Test that a request allows the three types of API authentication
204 #
204 #
205 # * HTTP Basic with username and password
205 # * HTTP Basic with username and password
206 # * HTTP Basic with an api key for the username
206 # * HTTP Basic with an api key for the username
207 # * Key based with the key=X parameter
207 # * Key based with the key=X parameter
208 #
208 #
209 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
209 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
210 # @param [String] url the request url
210 # @param [String] url the request url
211 # @param [optional, Hash] parameters additional request parameters
211 # @param [optional, Hash] parameters additional request parameters
212 # @param [optional, Hash] options additional options
212 # @param [optional, Hash] options additional options
213 # @option options [Symbol] :success_code Successful response code (:success)
213 # @option options [Symbol] :success_code Successful response code (:success)
214 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
214 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
215 def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
215 def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
216 should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options)
216 should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options)
217 should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
217 should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
218 should_allow_key_based_auth(http_method, url, parameters, options)
218 should_allow_key_based_auth(http_method, url, parameters, options)
219 end
219 end
220
220
221 # Test that a request allows the username and password for HTTP BASIC
221 # Test that a request allows the username and password for HTTP BASIC
222 #
222 #
223 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
223 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
224 # @param [String] url the request url
224 # @param [String] url the request url
225 # @param [optional, Hash] parameters additional request parameters
225 # @param [optional, Hash] parameters additional request parameters
226 # @param [optional, Hash] options additional options
226 # @param [optional, Hash] options additional options
227 # @option options [Symbol] :success_code Successful response code (:success)
227 # @option options [Symbol] :success_code Successful response code (:success)
228 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
228 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
229 def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
229 def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
230 success_code = options[:success_code] || :success
230 success_code = options[:success_code] || :success
231 failure_code = options[:failure_code] || :unauthorized
231 failure_code = options[:failure_code] || :unauthorized
232
232
233 context "should allow http basic auth using a username and password for #{http_method} #{url}" do
233 context "should allow http basic auth using a username and password for #{http_method} #{url}" do
234 context "with a valid HTTP authentication" do
234 context "with a valid HTTP authentication" do
235 setup do
235 setup do
236 @user = User.generate_with_protected!(:password => 'my_password', :password_confirmation => 'my_password', :admin => true) # Admin so they can access the project
236 @user = User.generate_with_protected!(:password => 'my_password', :password_confirmation => 'my_password', :admin => true) # Admin so they can access the project
237 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@user.login, 'my_password')
237 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@user.login, 'my_password')
238 send(http_method, url, parameters, {:authorization => @authorization})
238 send(http_method, url, parameters, {:authorization => @authorization})
239 end
239 end
240
240
241 should_respond_with success_code
241 should_respond_with success_code
242 should_respond_with_content_type_based_on_url(url)
242 should_respond_with_content_type_based_on_url(url)
243 should "login as the user" do
243 should "login as the user" do
244 assert_equal @user, User.current
244 assert_equal @user, User.current
245 end
245 end
246 end
246 end
247
247
248 context "with an invalid HTTP authentication" do
248 context "with an invalid HTTP authentication" do
249 setup do
249 setup do
250 @user = User.generate_with_protected!
250 @user = User.generate_with_protected!
251 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@user.login, 'wrong_password')
251 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@user.login, 'wrong_password')
252 send(http_method, url, parameters, {:authorization => @authorization})
252 send(http_method, url, parameters, {:authorization => @authorization})
253 end
253 end
254
254
255 should_respond_with failure_code
255 should_respond_with failure_code
256 should_respond_with_content_type_based_on_url(url)
256 should_respond_with_content_type_based_on_url(url)
257 should "not login as the user" do
257 should "not login as the user" do
258 assert_equal User.anonymous, User.current
258 assert_equal User.anonymous, User.current
259 end
259 end
260 end
260 end
261
261
262 context "without credentials" do
262 context "without credentials" do
263 setup do
263 setup do
264 send(http_method, url, parameters, {:authorization => ''})
264 send(http_method, url, parameters, {:authorization => ''})
265 end
265 end
266
266
267 should_respond_with failure_code
267 should_respond_with failure_code
268 should_respond_with_content_type_based_on_url(url)
268 should_respond_with_content_type_based_on_url(url)
269 should "include_www_authenticate_header" do
269 should "include_www_authenticate_header" do
270 assert @controller.response.headers.has_key?('WWW-Authenticate')
270 assert @controller.response.headers.has_key?('WWW-Authenticate')
271 end
271 end
272 end
272 end
273 end
273 end
274
274
275 end
275 end
276
276
277 # Test that a request allows the API key with HTTP BASIC
277 # Test that a request allows the API key with HTTP BASIC
278 #
278 #
279 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
279 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
280 # @param [String] url the request url
280 # @param [String] url the request url
281 # @param [optional, Hash] parameters additional request parameters
281 # @param [optional, Hash] parameters additional request parameters
282 # @param [optional, Hash] options additional options
282 # @param [optional, Hash] options additional options
283 # @option options [Symbol] :success_code Successful response code (:success)
283 # @option options [Symbol] :success_code Successful response code (:success)
284 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
284 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
285 def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
285 def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
286 success_code = options[:success_code] || :success
286 success_code = options[:success_code] || :success
287 failure_code = options[:failure_code] || :unauthorized
287 failure_code = options[:failure_code] || :unauthorized
288
288
289 context "should allow http basic auth with a key for #{http_method} #{url}" do
289 context "should allow http basic auth with a key for #{http_method} #{url}" do
290 context "with a valid HTTP authentication using the API token" do
290 context "with a valid HTTP authentication using the API token" do
291 setup do
291 setup do
292 @user = User.generate_with_protected!(:admin => true)
292 @user = User.generate_with_protected!(:admin => true)
293 @token = Token.generate!(:user => @user, :action => 'api')
293 @token = Token.generate!(:user => @user, :action => 'api')
294 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X')
294 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X')
295 send(http_method, url, parameters, {:authorization => @authorization})
295 send(http_method, url, parameters, {:authorization => @authorization})
296 end
296 end
297
297
298 should_respond_with success_code
298 should_respond_with success_code
299 should_respond_with_content_type_based_on_url(url)
299 should_respond_with_content_type_based_on_url(url)
300 should_be_a_valid_response_string_based_on_url(url)
300 should_be_a_valid_response_string_based_on_url(url)
301 should "login as the user" do
301 should "login as the user" do
302 assert_equal @user, User.current
302 assert_equal @user, User.current
303 end
303 end
304 end
304 end
305
305
306 context "with an invalid HTTP authentication" do
306 context "with an invalid HTTP authentication" do
307 setup do
307 setup do
308 @user = User.generate_with_protected!
308 @user = User.generate_with_protected!
309 @token = Token.generate!(:user => @user, :action => 'feeds')
309 @token = Token.generate!(:user => @user, :action => 'feeds')
310 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X')
310 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X')
311 send(http_method, url, parameters, {:authorization => @authorization})
311 send(http_method, url, parameters, {:authorization => @authorization})
312 end
312 end
313
313
314 should_respond_with failure_code
314 should_respond_with failure_code
315 should_respond_with_content_type_based_on_url(url)
315 should_respond_with_content_type_based_on_url(url)
316 should "not login as the user" do
316 should "not login as the user" do
317 assert_equal User.anonymous, User.current
317 assert_equal User.anonymous, User.current
318 end
318 end
319 end
319 end
320 end
320 end
321 end
321 end
322
322
323 # Test that a request allows full key authentication
323 # Test that a request allows full key authentication
324 #
324 #
325 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
325 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
326 # @param [String] url the request url, without the key=ZXY parameter
326 # @param [String] url the request url, without the key=ZXY parameter
327 # @param [optional, Hash] parameters additional request parameters
327 # @param [optional, Hash] parameters additional request parameters
328 # @param [optional, Hash] options additional options
328 # @param [optional, Hash] options additional options
329 # @option options [Symbol] :success_code Successful response code (:success)
329 # @option options [Symbol] :success_code Successful response code (:success)
330 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
330 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
331 def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
331 def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
332 success_code = options[:success_code] || :success
332 success_code = options[:success_code] || :success
333 failure_code = options[:failure_code] || :unauthorized
333 failure_code = options[:failure_code] || :unauthorized
334
334
335 context "should allow key based auth using key=X for #{http_method} #{url}" do
335 context "should allow key based auth using key=X for #{http_method} #{url}" do
336 context "with a valid api token" do
336 context "with a valid api token" do
337 setup do
337 setup do
338 @user = User.generate_with_protected!(:admin => true)
338 @user = User.generate_with_protected!(:admin => true)
339 @token = Token.generate!(:user => @user, :action => 'api')
339 @token = Token.generate!(:user => @user, :action => 'api')
340 # Simple url parse to add on ?key= or &key=
340 # Simple url parse to add on ?key= or &key=
341 request_url = if url.match(/\?/)
341 request_url = if url.match(/\?/)
342 url + "&key=#{@token.value}"
342 url + "&key=#{@token.value}"
343 else
343 else
344 url + "?key=#{@token.value}"
344 url + "?key=#{@token.value}"
345 end
345 end
346 send(http_method, request_url, parameters)
346 send(http_method, request_url, parameters)
347 end
347 end
348
348
349 should_respond_with success_code
349 should_respond_with success_code
350 should_respond_with_content_type_based_on_url(url)
350 should_respond_with_content_type_based_on_url(url)
351 should_be_a_valid_response_string_based_on_url(url)
351 should_be_a_valid_response_string_based_on_url(url)
352 should "login as the user" do
352 should "login as the user" do
353 assert_equal @user, User.current
353 assert_equal @user, User.current
354 end
354 end
355 end
355 end
356
356
357 context "with an invalid api token" do
357 context "with an invalid api token" do
358 setup do
358 setup do
359 @user = User.generate_with_protected!
359 @user = User.generate_with_protected!
360 @token = Token.generate!(:user => @user, :action => 'feeds')
360 @token = Token.generate!(:user => @user, :action => 'feeds')
361 # Simple url parse to add on ?key= or &key=
361 # Simple url parse to add on ?key= or &key=
362 request_url = if url.match(/\?/)
362 request_url = if url.match(/\?/)
363 url + "&key=#{@token.value}"
363 url + "&key=#{@token.value}"
364 else
364 else
365 url + "?key=#{@token.value}"
365 url + "?key=#{@token.value}"
366 end
366 end
367 send(http_method, request_url, parameters)
367 send(http_method, request_url, parameters)
368 end
368 end
369
369
370 should_respond_with failure_code
370 should_respond_with failure_code
371 should_respond_with_content_type_based_on_url(url)
371 should_respond_with_content_type_based_on_url(url)
372 should "not login as the user" do
372 should "not login as the user" do
373 assert_equal User.anonymous, User.current
373 assert_equal User.anonymous, User.current
374 end
374 end
375 end
375 end
376 end
376 end
377
377
378 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
378 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
379 setup do
379 setup do
380 @user = User.generate_with_protected!(:admin => true)
380 @user = User.generate_with_protected!(:admin => true)
381 @token = Token.generate!(:user => @user, :action => 'api')
381 @token = Token.generate!(:user => @user, :action => 'api')
382 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
382 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
383 end
383 end
384
384
385 should_respond_with success_code
385 should_respond_with success_code
386 should_respond_with_content_type_based_on_url(url)
386 should_respond_with_content_type_based_on_url(url)
387 should_be_a_valid_response_string_based_on_url(url)
387 should_be_a_valid_response_string_based_on_url(url)
388 should "login as the user" do
388 should "login as the user" do
389 assert_equal @user, User.current
389 assert_equal @user, User.current
390 end
390 end
391 end
391 end
392 end
392 end
393
393
394 # Uses should_respond_with_content_type based on what's in the url:
394 # Uses should_respond_with_content_type based on what's in the url:
395 #
395 #
396 # '/project/issues.xml' => should_respond_with_content_type :xml
396 # '/project/issues.xml' => should_respond_with_content_type :xml
397 # '/project/issues.json' => should_respond_with_content_type :json
397 # '/project/issues.json' => should_respond_with_content_type :json
398 #
398 #
399 # @param [String] url Request
399 # @param [String] url Request
400 def self.should_respond_with_content_type_based_on_url(url)
400 def self.should_respond_with_content_type_based_on_url(url)
401 case
401 case
402 when url.match(/xml/i)
402 when url.match(/xml/i)
403 should_respond_with_content_type :xml
403 should_respond_with_content_type :xml
404 when url.match(/json/i)
404 when url.match(/json/i)
405 should_respond_with_content_type :json
405 should_respond_with_content_type :json
406 else
406 else
407 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
407 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
408 end
408 end
409
409
410 end
410 end
411
411
412 # Uses the url to assert which format the response should be in
412 # Uses the url to assert which format the response should be in
413 #
413 #
414 # '/project/issues.xml' => should_be_a_valid_xml_string
414 # '/project/issues.xml' => should_be_a_valid_xml_string
415 # '/project/issues.json' => should_be_a_valid_json_string
415 # '/project/issues.json' => should_be_a_valid_json_string
416 #
416 #
417 # @param [String] url Request
417 # @param [String] url Request
418 def self.should_be_a_valid_response_string_based_on_url(url)
418 def self.should_be_a_valid_response_string_based_on_url(url)
419 case
419 case
420 when url.match(/xml/i)
420 when url.match(/xml/i)
421 should_be_a_valid_xml_string
421 should_be_a_valid_xml_string
422 when url.match(/json/i)
422 when url.match(/json/i)
423 should_be_a_valid_json_string
423 should_be_a_valid_json_string
424 else
424 else
425 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
425 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
426 end
426 end
427
427
428 end
428 end
429
429
430 # Checks that the response is a valid JSON string
430 # Checks that the response is a valid JSON string
431 def self.should_be_a_valid_json_string
431 def self.should_be_a_valid_json_string
432 should "be a valid JSON string (or empty)" do
432 should "be a valid JSON string (or empty)" do
433 assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
433 assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
434 end
434 end
435 end
435 end
436
436
437 # Checks that the response is a valid XML string
437 # Checks that the response is a valid XML string
438 def self.should_be_a_valid_xml_string
438 def self.should_be_a_valid_xml_string
439 should "be a valid XML string" do
439 should "be a valid XML string" do
440 assert REXML::Document.new(response.body)
440 assert REXML::Document.new(response.body)
441 end
441 end
442 end
442 end
443
443
444 end
444 end
445
445
446 # Simple module to "namespace" all of the API tests
446 # Simple module to "namespace" all of the API tests
447 module ApiTest
447 module ApiTest
448 end
448 end
General Comments 0
You need to be logged in to leave comments. Login now