##// END OF EJS Templates
code layout clean up uploaded_test_file of test/test_helper.rb...
Toshi MARUYAMA -
r7735:66d6d611baad
parent child
Show More
@@ -1,448 +1,449
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').to_s
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(
63 ActiveSupport::TestCase.fixture_path + "/files/#{name}", mime, true)
63 end
64 end
64
65
65 # Mock out a file
66 # Mock out a file
66 def self.mock_file
67 def self.mock_file
67 file = 'a_file.png'
68 file = 'a_file.png'
68 file.stubs(:size).returns(32)
69 file.stubs(:size).returns(32)
69 file.stubs(:original_filename).returns('a_file.png')
70 file.stubs(:original_filename).returns('a_file.png')
70 file.stubs(:content_type).returns('image/png')
71 file.stubs(:content_type).returns('image/png')
71 file.stubs(:read).returns(false)
72 file.stubs(:read).returns(false)
72 file
73 file
73 end
74 end
74
75
75 def mock_file
76 def mock_file
76 self.class.mock_file
77 self.class.mock_file
77 end
78 end
78
79
79 # Use a temporary directory for attachment related tests
80 # Use a temporary directory for attachment related tests
80 def set_tmp_attachments_directory
81 def set_tmp_attachments_directory
81 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
82 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
82 unless File.directory?("#{Rails.root}/tmp/test/attachments")
83 unless File.directory?("#{Rails.root}/tmp/test/attachments")
83 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
84 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
84 end
85 end
85 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
86 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
86 end
87 end
87
88
88 def with_settings(options, &block)
89 def with_settings(options, &block)
89 saved_settings = options.keys.inject({}) {|h, k| h[k] = Setting[k].dup; h}
90 saved_settings = options.keys.inject({}) {|h, k| h[k] = Setting[k].dup; h}
90 options.each {|k, v| Setting[k] = v}
91 options.each {|k, v| Setting[k] = v}
91 yield
92 yield
92 ensure
93 ensure
93 saved_settings.each {|k, v| Setting[k] = v}
94 saved_settings.each {|k, v| Setting[k] = v}
94 end
95 end
95
96
96 def change_user_password(login, new_password)
97 def change_user_password(login, new_password)
97 user = User.first(:conditions => {:login => login})
98 user = User.first(:conditions => {:login => login})
98 user.password, user.password_confirmation = new_password, new_password
99 user.password, user.password_confirmation = new_password, new_password
99 user.save!
100 user.save!
100 end
101 end
101
102
102 def self.ldap_configured?
103 def self.ldap_configured?
103 @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
104 @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
104 return @test_ldap.bind
105 return @test_ldap.bind
105 rescue Exception => e
106 rescue Exception => e
106 # LDAP is not listening
107 # LDAP is not listening
107 return nil
108 return nil
108 end
109 end
109
110
110 # Returns the path to the test +vendor+ repository
111 # Returns the path to the test +vendor+ repository
111 def self.repository_path(vendor)
112 def self.repository_path(vendor)
112 Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
113 Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
113 end
114 end
114
115
115 # Returns the url of the subversion test repository
116 # Returns the url of the subversion test repository
116 def self.subversion_repository_url
117 def self.subversion_repository_url
117 path = repository_path('subversion')
118 path = repository_path('subversion')
118 path = '/' + path unless path.starts_with?('/')
119 path = '/' + path unless path.starts_with?('/')
119 "file://#{path}"
120 "file://#{path}"
120 end
121 end
121
122
122 # Returns true if the +vendor+ test repository is configured
123 # Returns true if the +vendor+ test repository is configured
123 def self.repository_configured?(vendor)
124 def self.repository_configured?(vendor)
124 File.directory?(repository_path(vendor))
125 File.directory?(repository_path(vendor))
125 end
126 end
126
127
127 def assert_error_tag(options={})
128 def assert_error_tag(options={})
128 assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options))
129 assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options))
129 end
130 end
130
131
131 def assert_include(expected, s)
132 def assert_include(expected, s)
132 assert s.include?(expected), "\"#{expected}\" not found in \"#{s}\""
133 assert s.include?(expected), "\"#{expected}\" not found in \"#{s}\""
133 end
134 end
134
135
135 # Shoulda macros
136 # Shoulda macros
136 def self.should_render_404
137 def self.should_render_404
137 should_respond_with :not_found
138 should_respond_with :not_found
138 should_render_template 'common/error'
139 should_render_template 'common/error'
139 end
140 end
140
141
141 def self.should_have_before_filter(expected_method, options = {})
142 def self.should_have_before_filter(expected_method, options = {})
142 should_have_filter('before', expected_method, options)
143 should_have_filter('before', expected_method, options)
143 end
144 end
144
145
145 def self.should_have_after_filter(expected_method, options = {})
146 def self.should_have_after_filter(expected_method, options = {})
146 should_have_filter('after', expected_method, options)
147 should_have_filter('after', expected_method, options)
147 end
148 end
148
149
149 def self.should_have_filter(filter_type, expected_method, options)
150 def self.should_have_filter(filter_type, expected_method, options)
150 description = "have #{filter_type}_filter :#{expected_method}"
151 description = "have #{filter_type}_filter :#{expected_method}"
151 description << " with #{options.inspect}" unless options.empty?
152 description << " with #{options.inspect}" unless options.empty?
152
153
153 should description do
154 should description do
154 klass = "action_controller/filters/#{filter_type}_filter".classify.constantize
155 klass = "action_controller/filters/#{filter_type}_filter".classify.constantize
155 expected = klass.new(:filter, expected_method.to_sym, options)
156 expected = klass.new(:filter, expected_method.to_sym, options)
156 assert_equal 1, @controller.class.filter_chain.select { |filter|
157 assert_equal 1, @controller.class.filter_chain.select { |filter|
157 filter.method == expected.method && filter.kind == expected.kind &&
158 filter.method == expected.method && filter.kind == expected.kind &&
158 filter.options == expected.options && filter.class == expected.class
159 filter.options == expected.options && filter.class == expected.class
159 }.size
160 }.size
160 end
161 end
161 end
162 end
162
163
163 def self.should_show_the_old_and_new_values_for(prop_key, model, &block)
164 def self.should_show_the_old_and_new_values_for(prop_key, model, &block)
164 context "" do
165 context "" do
165 setup do
166 setup do
166 if block_given?
167 if block_given?
167 instance_eval &block
168 instance_eval &block
168 else
169 else
169 @old_value = model.generate!
170 @old_value = model.generate!
170 @new_value = model.generate!
171 @new_value = model.generate!
171 end
172 end
172 end
173 end
173
174
174 should "use the new value's name" do
175 should "use the new value's name" do
175 @detail = JournalDetail.generate!(:property => 'attr',
176 @detail = JournalDetail.generate!(:property => 'attr',
176 :old_value => @old_value.id,
177 :old_value => @old_value.id,
177 :value => @new_value.id,
178 :value => @new_value.id,
178 :prop_key => prop_key)
179 :prop_key => prop_key)
179
180
180 assert_match @new_value.name, show_detail(@detail, true)
181 assert_match @new_value.name, show_detail(@detail, true)
181 end
182 end
182
183
183 should "use the old value's name" do
184 should "use the old value's name" do
184 @detail = JournalDetail.generate!(:property => 'attr',
185 @detail = JournalDetail.generate!(:property => 'attr',
185 :old_value => @old_value.id,
186 :old_value => @old_value.id,
186 :value => @new_value.id,
187 :value => @new_value.id,
187 :prop_key => prop_key)
188 :prop_key => prop_key)
188
189
189 assert_match @old_value.name, show_detail(@detail, true)
190 assert_match @old_value.name, show_detail(@detail, true)
190 end
191 end
191 end
192 end
192 end
193 end
193
194
194 def self.should_create_a_new_user(&block)
195 def self.should_create_a_new_user(&block)
195 should "create a new user" do
196 should "create a new user" do
196 user = instance_eval &block
197 user = instance_eval &block
197 assert user
198 assert user
198 assert_kind_of User, user
199 assert_kind_of User, user
199 assert !user.new_record?
200 assert !user.new_record?
200 end
201 end
201 end
202 end
202
203
203 # Test that a request allows the three types of API authentication
204 # Test that a request allows the three types of API authentication
204 #
205 #
205 # * HTTP Basic with username and password
206 # * HTTP Basic with username and password
206 # * HTTP Basic with an api key for the username
207 # * HTTP Basic with an api key for the username
207 # * Key based with the key=X parameter
208 # * Key based with the key=X parameter
208 #
209 #
209 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
210 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
210 # @param [String] url the request url
211 # @param [String] url the request url
211 # @param [optional, Hash] parameters additional request parameters
212 # @param [optional, Hash] parameters additional request parameters
212 # @param [optional, Hash] options additional options
213 # @param [optional, Hash] options additional options
213 # @option options [Symbol] :success_code Successful response code (:success)
214 # @option options [Symbol] :success_code Successful response code (:success)
214 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
215 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
215 def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
216 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)
217 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)
218 should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
218 should_allow_key_based_auth(http_method, url, parameters, options)
219 should_allow_key_based_auth(http_method, url, parameters, options)
219 end
220 end
220
221
221 # Test that a request allows the username and password for HTTP BASIC
222 # Test that a request allows the username and password for HTTP BASIC
222 #
223 #
223 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
224 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
224 # @param [String] url the request url
225 # @param [String] url the request url
225 # @param [optional, Hash] parameters additional request parameters
226 # @param [optional, Hash] parameters additional request parameters
226 # @param [optional, Hash] options additional options
227 # @param [optional, Hash] options additional options
227 # @option options [Symbol] :success_code Successful response code (:success)
228 # @option options [Symbol] :success_code Successful response code (:success)
228 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
229 # @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={})
230 def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
230 success_code = options[:success_code] || :success
231 success_code = options[:success_code] || :success
231 failure_code = options[:failure_code] || :unauthorized
232 failure_code = options[:failure_code] || :unauthorized
232
233
233 context "should allow http basic auth using a username and password for #{http_method} #{url}" do
234 context "should allow http basic auth using a username and password for #{http_method} #{url}" do
234 context "with a valid HTTP authentication" do
235 context "with a valid HTTP authentication" do
235 setup do
236 setup do
236 @user = User.generate_with_protected!(:password => 'my_password', :password_confirmation => 'my_password', :admin => true) # Admin so they can access the project
237 @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')
238 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@user.login, 'my_password')
238 send(http_method, url, parameters, {:authorization => @authorization})
239 send(http_method, url, parameters, {:authorization => @authorization})
239 end
240 end
240
241
241 should_respond_with success_code
242 should_respond_with success_code
242 should_respond_with_content_type_based_on_url(url)
243 should_respond_with_content_type_based_on_url(url)
243 should "login as the user" do
244 should "login as the user" do
244 assert_equal @user, User.current
245 assert_equal @user, User.current
245 end
246 end
246 end
247 end
247
248
248 context "with an invalid HTTP authentication" do
249 context "with an invalid HTTP authentication" do
249 setup do
250 setup do
250 @user = User.generate_with_protected!
251 @user = User.generate_with_protected!
251 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@user.login, 'wrong_password')
252 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@user.login, 'wrong_password')
252 send(http_method, url, parameters, {:authorization => @authorization})
253 send(http_method, url, parameters, {:authorization => @authorization})
253 end
254 end
254
255
255 should_respond_with failure_code
256 should_respond_with failure_code
256 should_respond_with_content_type_based_on_url(url)
257 should_respond_with_content_type_based_on_url(url)
257 should "not login as the user" do
258 should "not login as the user" do
258 assert_equal User.anonymous, User.current
259 assert_equal User.anonymous, User.current
259 end
260 end
260 end
261 end
261
262
262 context "without credentials" do
263 context "without credentials" do
263 setup do
264 setup do
264 send(http_method, url, parameters, {:authorization => ''})
265 send(http_method, url, parameters, {:authorization => ''})
265 end
266 end
266
267
267 should_respond_with failure_code
268 should_respond_with failure_code
268 should_respond_with_content_type_based_on_url(url)
269 should_respond_with_content_type_based_on_url(url)
269 should "include_www_authenticate_header" do
270 should "include_www_authenticate_header" do
270 assert @controller.response.headers.has_key?('WWW-Authenticate')
271 assert @controller.response.headers.has_key?('WWW-Authenticate')
271 end
272 end
272 end
273 end
273 end
274 end
274
275
275 end
276 end
276
277
277 # Test that a request allows the API key with HTTP BASIC
278 # Test that a request allows the API key with HTTP BASIC
278 #
279 #
279 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
280 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
280 # @param [String] url the request url
281 # @param [String] url the request url
281 # @param [optional, Hash] parameters additional request parameters
282 # @param [optional, Hash] parameters additional request parameters
282 # @param [optional, Hash] options additional options
283 # @param [optional, Hash] options additional options
283 # @option options [Symbol] :success_code Successful response code (:success)
284 # @option options [Symbol] :success_code Successful response code (:success)
284 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
285 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
285 def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
286 def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
286 success_code = options[:success_code] || :success
287 success_code = options[:success_code] || :success
287 failure_code = options[:failure_code] || :unauthorized
288 failure_code = options[:failure_code] || :unauthorized
288
289
289 context "should allow http basic auth with a key for #{http_method} #{url}" do
290 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
291 context "with a valid HTTP authentication using the API token" do
291 setup do
292 setup do
292 @user = User.generate_with_protected!(:admin => true)
293 @user = User.generate_with_protected!(:admin => true)
293 @token = Token.generate!(:user => @user, :action => 'api')
294 @token = Token.generate!(:user => @user, :action => 'api')
294 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X')
295 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X')
295 send(http_method, url, parameters, {:authorization => @authorization})
296 send(http_method, url, parameters, {:authorization => @authorization})
296 end
297 end
297
298
298 should_respond_with success_code
299 should_respond_with success_code
299 should_respond_with_content_type_based_on_url(url)
300 should_respond_with_content_type_based_on_url(url)
300 should_be_a_valid_response_string_based_on_url(url)
301 should_be_a_valid_response_string_based_on_url(url)
301 should "login as the user" do
302 should "login as the user" do
302 assert_equal @user, User.current
303 assert_equal @user, User.current
303 end
304 end
304 end
305 end
305
306
306 context "with an invalid HTTP authentication" do
307 context "with an invalid HTTP authentication" do
307 setup do
308 setup do
308 @user = User.generate_with_protected!
309 @user = User.generate_with_protected!
309 @token = Token.generate!(:user => @user, :action => 'feeds')
310 @token = Token.generate!(:user => @user, :action => 'feeds')
310 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X')
311 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X')
311 send(http_method, url, parameters, {:authorization => @authorization})
312 send(http_method, url, parameters, {:authorization => @authorization})
312 end
313 end
313
314
314 should_respond_with failure_code
315 should_respond_with failure_code
315 should_respond_with_content_type_based_on_url(url)
316 should_respond_with_content_type_based_on_url(url)
316 should "not login as the user" do
317 should "not login as the user" do
317 assert_equal User.anonymous, User.current
318 assert_equal User.anonymous, User.current
318 end
319 end
319 end
320 end
320 end
321 end
321 end
322 end
322
323
323 # Test that a request allows full key authentication
324 # Test that a request allows full key authentication
324 #
325 #
325 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
326 # @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
327 # @param [String] url the request url, without the key=ZXY parameter
327 # @param [optional, Hash] parameters additional request parameters
328 # @param [optional, Hash] parameters additional request parameters
328 # @param [optional, Hash] options additional options
329 # @param [optional, Hash] options additional options
329 # @option options [Symbol] :success_code Successful response code (:success)
330 # @option options [Symbol] :success_code Successful response code (:success)
330 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
331 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
331 def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
332 def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
332 success_code = options[:success_code] || :success
333 success_code = options[:success_code] || :success
333 failure_code = options[:failure_code] || :unauthorized
334 failure_code = options[:failure_code] || :unauthorized
334
335
335 context "should allow key based auth using key=X for #{http_method} #{url}" do
336 context "should allow key based auth using key=X for #{http_method} #{url}" do
336 context "with a valid api token" do
337 context "with a valid api token" do
337 setup do
338 setup do
338 @user = User.generate_with_protected!(:admin => true)
339 @user = User.generate_with_protected!(:admin => true)
339 @token = Token.generate!(:user => @user, :action => 'api')
340 @token = Token.generate!(:user => @user, :action => 'api')
340 # Simple url parse to add on ?key= or &key=
341 # Simple url parse to add on ?key= or &key=
341 request_url = if url.match(/\?/)
342 request_url = if url.match(/\?/)
342 url + "&key=#{@token.value}"
343 url + "&key=#{@token.value}"
343 else
344 else
344 url + "?key=#{@token.value}"
345 url + "?key=#{@token.value}"
345 end
346 end
346 send(http_method, request_url, parameters)
347 send(http_method, request_url, parameters)
347 end
348 end
348
349
349 should_respond_with success_code
350 should_respond_with success_code
350 should_respond_with_content_type_based_on_url(url)
351 should_respond_with_content_type_based_on_url(url)
351 should_be_a_valid_response_string_based_on_url(url)
352 should_be_a_valid_response_string_based_on_url(url)
352 should "login as the user" do
353 should "login as the user" do
353 assert_equal @user, User.current
354 assert_equal @user, User.current
354 end
355 end
355 end
356 end
356
357
357 context "with an invalid api token" do
358 context "with an invalid api token" do
358 setup do
359 setup do
359 @user = User.generate_with_protected!
360 @user = User.generate_with_protected!
360 @token = Token.generate!(:user => @user, :action => 'feeds')
361 @token = Token.generate!(:user => @user, :action => 'feeds')
361 # Simple url parse to add on ?key= or &key=
362 # Simple url parse to add on ?key= or &key=
362 request_url = if url.match(/\?/)
363 request_url = if url.match(/\?/)
363 url + "&key=#{@token.value}"
364 url + "&key=#{@token.value}"
364 else
365 else
365 url + "?key=#{@token.value}"
366 url + "?key=#{@token.value}"
366 end
367 end
367 send(http_method, request_url, parameters)
368 send(http_method, request_url, parameters)
368 end
369 end
369
370
370 should_respond_with failure_code
371 should_respond_with failure_code
371 should_respond_with_content_type_based_on_url(url)
372 should_respond_with_content_type_based_on_url(url)
372 should "not login as the user" do
373 should "not login as the user" do
373 assert_equal User.anonymous, User.current
374 assert_equal User.anonymous, User.current
374 end
375 end
375 end
376 end
376 end
377 end
377
378
378 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
379 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
379 setup do
380 setup do
380 @user = User.generate_with_protected!(:admin => true)
381 @user = User.generate_with_protected!(:admin => true)
381 @token = Token.generate!(:user => @user, :action => 'api')
382 @token = Token.generate!(:user => @user, :action => 'api')
382 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
383 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
383 end
384 end
384
385
385 should_respond_with success_code
386 should_respond_with success_code
386 should_respond_with_content_type_based_on_url(url)
387 should_respond_with_content_type_based_on_url(url)
387 should_be_a_valid_response_string_based_on_url(url)
388 should_be_a_valid_response_string_based_on_url(url)
388 should "login as the user" do
389 should "login as the user" do
389 assert_equal @user, User.current
390 assert_equal @user, User.current
390 end
391 end
391 end
392 end
392 end
393 end
393
394
394 # Uses should_respond_with_content_type based on what's in the url:
395 # Uses should_respond_with_content_type based on what's in the url:
395 #
396 #
396 # '/project/issues.xml' => should_respond_with_content_type :xml
397 # '/project/issues.xml' => should_respond_with_content_type :xml
397 # '/project/issues.json' => should_respond_with_content_type :json
398 # '/project/issues.json' => should_respond_with_content_type :json
398 #
399 #
399 # @param [String] url Request
400 # @param [String] url Request
400 def self.should_respond_with_content_type_based_on_url(url)
401 def self.should_respond_with_content_type_based_on_url(url)
401 case
402 case
402 when url.match(/xml/i)
403 when url.match(/xml/i)
403 should_respond_with_content_type :xml
404 should_respond_with_content_type :xml
404 when url.match(/json/i)
405 when url.match(/json/i)
405 should_respond_with_content_type :json
406 should_respond_with_content_type :json
406 else
407 else
407 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
408 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
408 end
409 end
409
410
410 end
411 end
411
412
412 # Uses the url to assert which format the response should be in
413 # Uses the url to assert which format the response should be in
413 #
414 #
414 # '/project/issues.xml' => should_be_a_valid_xml_string
415 # '/project/issues.xml' => should_be_a_valid_xml_string
415 # '/project/issues.json' => should_be_a_valid_json_string
416 # '/project/issues.json' => should_be_a_valid_json_string
416 #
417 #
417 # @param [String] url Request
418 # @param [String] url Request
418 def self.should_be_a_valid_response_string_based_on_url(url)
419 def self.should_be_a_valid_response_string_based_on_url(url)
419 case
420 case
420 when url.match(/xml/i)
421 when url.match(/xml/i)
421 should_be_a_valid_xml_string
422 should_be_a_valid_xml_string
422 when url.match(/json/i)
423 when url.match(/json/i)
423 should_be_a_valid_json_string
424 should_be_a_valid_json_string
424 else
425 else
425 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
426 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
426 end
427 end
427
428
428 end
429 end
429
430
430 # Checks that the response is a valid JSON string
431 # Checks that the response is a valid JSON string
431 def self.should_be_a_valid_json_string
432 def self.should_be_a_valid_json_string
432 should "be a valid JSON string (or empty)" do
433 should "be a valid JSON string (or empty)" do
433 assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
434 assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
434 end
435 end
435 end
436 end
436
437
437 # Checks that the response is a valid XML string
438 # Checks that the response is a valid XML string
438 def self.should_be_a_valid_xml_string
439 def self.should_be_a_valid_xml_string
439 should "be a valid XML string" do
440 should "be a valid XML string" do
440 assert REXML::Document.new(response.body)
441 assert REXML::Document.new(response.body)
441 end
442 end
442 end
443 end
443
444
444 end
445 end
445
446
446 # Simple module to "namespace" all of the API tests
447 # Simple module to "namespace" all of the API tests
447 module ApiTest
448 module ApiTest
448 end
449 end
General Comments 0
You need to be logged in to leave comments. Login now