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