Mercurial > hg > soundsoftware-site
comparison test/test_helper.rb @ 1115:433d4f72a19b redmine-2.2
Update to Redmine SVN revision 11137 on 2.2-stable branch
author | Chris Cannam |
---|---|
date | Mon, 07 Jan 2013 12:01:42 +0000 |
parents | cbb26bc654de |
children | bb32da3bea34 622f24f53b42 261b3d9a4903 |
comparison
equal
deleted
inserted
replaced
929:5f33065ddc4b | 1115:433d4f72a19b |
---|---|
1 # Redmine - project management software | 1 # Redmine - project management software |
2 # Copyright (C) 2006-2011 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. |
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 ENV["RAILS_ENV"] = "test" | 19 ENV["RAILS_ENV"] = "test" |
19 require File.expand_path(File.dirname(__FILE__) + "/../config/environment") | 20 require File.expand_path(File.dirname(__FILE__) + "/../config/environment") |
20 require 'test_help' | 21 require 'rails/test_help' |
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_helpers') |
25 include ObjectDaddyHelpers | 25 include ObjectHelpers |
26 | 26 |
27 class ActiveSupport::TestCase | 27 class ActiveSupport::TestCase |
28 include ActionDispatch::TestProcess | |
29 | |
28 # Transactional fixtures accelerate your tests by wrapping each test method | 30 # Transactional fixtures accelerate your tests by wrapping each test method |
29 # 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 |
30 # 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 |
31 # between every test method. Fewer database queries means faster tests. | 33 # between every test method. Fewer database queries means faster tests. |
32 # | 34 # |
57 post "/login", :username => login, :password => password | 59 post "/login", :username => login, :password => password |
58 assert_equal login, User.find(session[:user_id]).login | 60 assert_equal login, User.find(session[:user_id]).login |
59 end | 61 end |
60 | 62 |
61 def uploaded_test_file(name, mime) | 63 def uploaded_test_file(name, mime) |
62 ActionController::TestUploadedFile.new( | 64 fixture_file_upload("files/#{name}", mime, true) |
63 ActiveSupport::TestCase.fixture_path + "/files/#{name}", mime, true) | 65 end |
66 | |
67 def credentials(user, password=nil) | |
68 {'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)} | |
64 end | 69 end |
65 | 70 |
66 # Mock out a file | 71 # Mock out a file |
67 def self.mock_file | 72 def self.mock_file |
68 file = 'a_file.png' | 73 file = 'a_file.png' |
95 Dir.mkdir "#{Rails.root}/tmp/test/attachments" | 100 Dir.mkdir "#{Rails.root}/tmp/test/attachments" |
96 end | 101 end |
97 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments" | 102 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments" |
98 end | 103 end |
99 | 104 |
105 def set_fixtures_attachments_directory | |
106 Attachment.storage_path = "#{Rails.root}/test/fixtures/files" | |
107 end | |
108 | |
100 def with_settings(options, &block) | 109 def with_settings(options, &block) |
101 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} |
102 options.each {|k, v| Setting[k] = v} | 111 options.each {|k, v| Setting[k] = v} |
103 yield | 112 yield |
104 ensure | 113 ensure |
105 saved_settings.each {|k, v| Setting[k] = v} if saved_settings | 114 saved_settings.each {|k, v| Setting[k] = v} if saved_settings |
106 end | 115 end |
107 | 116 |
117 # Yields the block with user as the current user | |
118 def with_current_user(user, &block) | |
119 saved_user = User.current | |
120 User.current = user | |
121 yield | |
122 ensure | |
123 User.current = saved_user | |
124 end | |
125 | |
108 def change_user_password(login, new_password) | 126 def change_user_password(login, new_password) |
109 user = User.first(:conditions => {:login => login}) | 127 user = User.first(:conditions => {:login => login}) |
110 user.password, user.password_confirmation = new_password, new_password | 128 user.password, user.password_confirmation = new_password, new_password |
111 user.save! | 129 user.save! |
112 end | 130 end |
117 rescue Exception => e | 135 rescue Exception => e |
118 # LDAP is not listening | 136 # LDAP is not listening |
119 return nil | 137 return nil |
120 end | 138 end |
121 | 139 |
140 def self.convert_installed? | |
141 Redmine::Thumbnail.convert_available? | |
142 end | |
143 | |
122 # Returns the path to the test +vendor+ repository | 144 # Returns the path to the test +vendor+ repository |
123 def self.repository_path(vendor) | 145 def self.repository_path(vendor) |
124 Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s | 146 Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s |
125 end | 147 end |
126 | 148 |
134 # Returns true if the +vendor+ test repository is configured | 156 # Returns true if the +vendor+ test repository is configured |
135 def self.repository_configured?(vendor) | 157 def self.repository_configured?(vendor) |
136 File.directory?(repository_path(vendor)) | 158 File.directory?(repository_path(vendor)) |
137 end | 159 end |
138 | 160 |
161 def repository_path_hash(arr) | |
162 hs = {} | |
163 hs[:path] = arr.join("/") | |
164 hs[:param] = arr.join("/") | |
165 hs | |
166 end | |
167 | |
168 def assert_save(object) | |
169 saved = object.save | |
170 message = "#{object.class} could not be saved" | |
171 errors = object.errors.full_messages.map {|m| "- #{m}"} | |
172 message << ":\n#{errors.join("\n")}" if errors.any? | |
173 assert_equal true, saved, message | |
174 end | |
175 | |
139 def assert_error_tag(options={}) | 176 def assert_error_tag(options={}) |
140 assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options)) | 177 assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options)) |
141 end | 178 end |
142 | 179 |
143 def assert_include(expected, s) | 180 def assert_include(expected, s, message=nil) |
144 assert s.include?(expected), "\"#{expected}\" not found in \"#{s}\"" | 181 assert s.include?(expected), (message || "\"#{expected}\" not found in \"#{s}\"") |
182 end | |
183 | |
184 def assert_not_include(expected, s) | |
185 assert !s.include?(expected), "\"#{expected}\" found in \"#{s}\"" | |
186 end | |
187 | |
188 def assert_select_in(text, *args, &block) | |
189 d = HTML::Document.new(CGI::unescapeHTML(String.new(text))).root | |
190 assert_select(d, *args, &block) | |
191 end | |
192 | |
193 def assert_mail_body_match(expected, mail) | |
194 if expected.is_a?(String) | |
195 assert_include expected, mail_body(mail) | |
196 else | |
197 assert_match expected, mail_body(mail) | |
198 end | |
199 end | |
200 | |
201 def assert_mail_body_no_match(expected, mail) | |
202 if expected.is_a?(String) | |
203 assert_not_include expected, mail_body(mail) | |
204 else | |
205 assert_no_match expected, mail_body(mail) | |
206 end | |
207 end | |
208 | |
209 def mail_body(mail) | |
210 mail.parts.first.body.encoded | |
145 end | 211 end |
146 | 212 |
147 # Shoulda macros | 213 # Shoulda macros |
148 def self.should_render_404 | 214 def self.should_render_404 |
149 should_respond_with :not_found | 215 should_respond_with :not_found |
167 expected = klass.new(:filter, expected_method.to_sym, options) | 233 expected = klass.new(:filter, expected_method.to_sym, options) |
168 assert_equal 1, @controller.class.filter_chain.select { |filter| | 234 assert_equal 1, @controller.class.filter_chain.select { |filter| |
169 filter.method == expected.method && filter.kind == expected.kind && | 235 filter.method == expected.method && filter.kind == expected.kind && |
170 filter.options == expected.options && filter.class == expected.class | 236 filter.options == expected.options && filter.class == expected.class |
171 }.size | 237 }.size |
172 end | |
173 end | |
174 | |
175 def self.should_show_the_old_and_new_values_for(prop_key, model, &block) | |
176 context "" do | |
177 setup do | |
178 if block_given? | |
179 instance_eval &block | |
180 else | |
181 @old_value = model.generate! | |
182 @new_value = model.generate! | |
183 end | |
184 end | |
185 | |
186 should "use the new value's name" do | |
187 @detail = JournalDetail.generate!(:property => 'attr', | |
188 :old_value => @old_value.id, | |
189 :value => @new_value.id, | |
190 :prop_key => prop_key) | |
191 | |
192 assert_match @new_value.name, show_detail(@detail, true) | |
193 end | |
194 | |
195 should "use the old value's name" do | |
196 @detail = JournalDetail.generate!(:property => 'attr', | |
197 :old_value => @old_value.id, | |
198 :value => @new_value.id, | |
199 :prop_key => prop_key) | |
200 | |
201 assert_match @old_value.name, show_detail(@detail, true) | |
202 end | |
203 end | |
204 end | |
205 | |
206 def self.should_create_a_new_user(&block) | |
207 should "create a new user" do | |
208 user = instance_eval &block | |
209 assert user | |
210 assert_kind_of User, user | |
211 assert !user.new_record? | |
212 end | 238 end |
213 end | 239 end |
214 | 240 |
215 # Test that a request allows the three types of API authentication | 241 # Test that a request allows the three types of API authentication |
216 # | 242 # |
243 failure_code = options[:failure_code] || :unauthorized | 269 failure_code = options[:failure_code] || :unauthorized |
244 | 270 |
245 context "should allow http basic auth using a username and password for #{http_method} #{url}" do | 271 context "should allow http basic auth using a username and password for #{http_method} #{url}" do |
246 context "with a valid HTTP authentication" do | 272 context "with a valid HTTP authentication" do |
247 setup do | 273 setup do |
248 @user = User.generate_with_protected!(:password => 'my_password', :password_confirmation => 'my_password', :admin => true) # Admin so they can access the project | 274 @user = User.generate! do |user| |
249 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@user.login, 'my_password') | 275 user.admin = true |
250 send(http_method, url, parameters, {:authorization => @authorization}) | 276 user.password = 'my_password' |
277 end | |
278 send(http_method, url, parameters, credentials(@user.login, 'my_password')) | |
251 end | 279 end |
252 | 280 |
253 should_respond_with success_code | 281 should_respond_with success_code |
254 should_respond_with_content_type_based_on_url(url) | 282 should_respond_with_content_type_based_on_url(url) |
255 should "login as the user" do | 283 should "login as the user" do |
257 end | 285 end |
258 end | 286 end |
259 | 287 |
260 context "with an invalid HTTP authentication" do | 288 context "with an invalid HTTP authentication" do |
261 setup do | 289 setup do |
262 @user = User.generate_with_protected! | 290 @user = User.generate! |
263 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@user.login, 'wrong_password') | 291 send(http_method, url, parameters, credentials(@user.login, 'wrong_password')) |
264 send(http_method, url, parameters, {:authorization => @authorization}) | |
265 end | 292 end |
266 | 293 |
267 should_respond_with failure_code | 294 should_respond_with failure_code |
268 should_respond_with_content_type_based_on_url(url) | 295 should_respond_with_content_type_based_on_url(url) |
269 should "not login as the user" do | 296 should "not login as the user" do |
271 end | 298 end |
272 end | 299 end |
273 | 300 |
274 context "without credentials" do | 301 context "without credentials" do |
275 setup do | 302 setup do |
276 send(http_method, url, parameters, {:authorization => ''}) | 303 send(http_method, url, parameters) |
277 end | 304 end |
278 | 305 |
279 should_respond_with failure_code | 306 should_respond_with failure_code |
280 should_respond_with_content_type_based_on_url(url) | 307 should_respond_with_content_type_based_on_url(url) |
281 should "include_www_authenticate_header" do | 308 should "include_www_authenticate_header" do |
282 assert @controller.response.headers.has_key?('WWW-Authenticate') | 309 assert @controller.response.headers.has_key?('WWW-Authenticate') |
283 end | 310 end |
284 end | 311 end |
285 end | 312 end |
286 | |
287 end | 313 end |
288 | 314 |
289 # Test that a request allows the API key with HTTP BASIC | 315 # Test that a request allows the API key with HTTP BASIC |
290 # | 316 # |
291 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete) | 317 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete) |
299 failure_code = options[:failure_code] || :unauthorized | 325 failure_code = options[:failure_code] || :unauthorized |
300 | 326 |
301 context "should allow http basic auth with a key for #{http_method} #{url}" do | 327 context "should allow http basic auth with a key for #{http_method} #{url}" do |
302 context "with a valid HTTP authentication using the API token" do | 328 context "with a valid HTTP authentication using the API token" do |
303 setup do | 329 setup do |
304 @user = User.generate_with_protected!(:admin => true) | 330 @user = User.generate! do |user| |
305 @token = Token.generate!(:user => @user, :action => 'api') | 331 user.admin = true |
306 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X') | 332 end |
307 send(http_method, url, parameters, {:authorization => @authorization}) | 333 @token = Token.create!(:user => @user, :action => 'api') |
308 end | 334 send(http_method, url, parameters, credentials(@token.value, 'X')) |
309 | 335 end |
310 should_respond_with success_code | 336 should_respond_with success_code |
311 should_respond_with_content_type_based_on_url(url) | 337 should_respond_with_content_type_based_on_url(url) |
312 should_be_a_valid_response_string_based_on_url(url) | 338 should_be_a_valid_response_string_based_on_url(url) |
313 should "login as the user" do | 339 should "login as the user" do |
314 assert_equal @user, User.current | 340 assert_equal @user, User.current |
315 end | 341 end |
316 end | 342 end |
317 | 343 |
318 context "with an invalid HTTP authentication" do | 344 context "with an invalid HTTP authentication" do |
319 setup do | 345 setup do |
320 @user = User.generate_with_protected! | 346 @user = User.generate! |
321 @token = Token.generate!(:user => @user, :action => 'feeds') | 347 @token = Token.create!(:user => @user, :action => 'feeds') |
322 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X') | 348 send(http_method, url, parameters, credentials(@token.value, 'X')) |
323 send(http_method, url, parameters, {:authorization => @authorization}) | 349 end |
324 end | |
325 | |
326 should_respond_with failure_code | 350 should_respond_with failure_code |
327 should_respond_with_content_type_based_on_url(url) | 351 should_respond_with_content_type_based_on_url(url) |
328 should "not login as the user" do | 352 should "not login as the user" do |
329 assert_equal User.anonymous, User.current | 353 assert_equal User.anonymous, User.current |
330 end | 354 end |
345 failure_code = options[:failure_code] || :unauthorized | 369 failure_code = options[:failure_code] || :unauthorized |
346 | 370 |
347 context "should allow key based auth using key=X for #{http_method} #{url}" do | 371 context "should allow key based auth using key=X for #{http_method} #{url}" do |
348 context "with a valid api token" do | 372 context "with a valid api token" do |
349 setup do | 373 setup do |
350 @user = User.generate_with_protected!(:admin => true) | 374 @user = User.generate! do |user| |
351 @token = Token.generate!(:user => @user, :action => 'api') | 375 user.admin = true |
376 end | |
377 @token = Token.create!(:user => @user, :action => 'api') | |
352 # Simple url parse to add on ?key= or &key= | 378 # Simple url parse to add on ?key= or &key= |
353 request_url = if url.match(/\?/) | 379 request_url = if url.match(/\?/) |
354 url + "&key=#{@token.value}" | 380 url + "&key=#{@token.value}" |
355 else | 381 else |
356 url + "?key=#{@token.value}" | 382 url + "?key=#{@token.value}" |
357 end | 383 end |
358 send(http_method, request_url, parameters) | 384 send(http_method, request_url, parameters) |
359 end | 385 end |
360 | |
361 should_respond_with success_code | 386 should_respond_with success_code |
362 should_respond_with_content_type_based_on_url(url) | 387 should_respond_with_content_type_based_on_url(url) |
363 should_be_a_valid_response_string_based_on_url(url) | 388 should_be_a_valid_response_string_based_on_url(url) |
364 should "login as the user" do | 389 should "login as the user" do |
365 assert_equal @user, User.current | 390 assert_equal @user, User.current |
366 end | 391 end |
367 end | 392 end |
368 | 393 |
369 context "with an invalid api token" do | 394 context "with an invalid api token" do |
370 setup do | 395 setup do |
371 @user = User.generate_with_protected! | 396 @user = User.generate! do |user| |
372 @token = Token.generate!(:user => @user, :action => 'feeds') | 397 user.admin = true |
398 end | |
399 @token = Token.create!(:user => @user, :action => 'feeds') | |
373 # Simple url parse to add on ?key= or &key= | 400 # Simple url parse to add on ?key= or &key= |
374 request_url = if url.match(/\?/) | 401 request_url = if url.match(/\?/) |
375 url + "&key=#{@token.value}" | 402 url + "&key=#{@token.value}" |
376 else | 403 else |
377 url + "?key=#{@token.value}" | 404 url + "?key=#{@token.value}" |
378 end | 405 end |
379 send(http_method, request_url, parameters) | 406 send(http_method, request_url, parameters) |
380 end | 407 end |
381 | |
382 should_respond_with failure_code | 408 should_respond_with failure_code |
383 should_respond_with_content_type_based_on_url(url) | 409 should_respond_with_content_type_based_on_url(url) |
384 should "not login as the user" do | 410 should "not login as the user" do |
385 assert_equal User.anonymous, User.current | 411 assert_equal User.anonymous, User.current |
386 end | 412 end |
387 end | 413 end |
388 end | 414 end |
389 | 415 |
390 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do | 416 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do |
391 setup do | 417 setup do |
392 @user = User.generate_with_protected!(:admin => true) | 418 @user = User.generate! do |user| |
393 @token = Token.generate!(:user => @user, :action => 'api') | 419 user.admin = true |
420 end | |
421 @token = Token.create!(:user => @user, :action => 'api') | |
394 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s}) | 422 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s}) |
395 end | 423 end |
396 | |
397 should_respond_with success_code | 424 should_respond_with success_code |
398 should_respond_with_content_type_based_on_url(url) | 425 should_respond_with_content_type_based_on_url(url) |
399 should_be_a_valid_response_string_based_on_url(url) | 426 should_be_a_valid_response_string_based_on_url(url) |
400 should "login as the user" do | 427 should "login as the user" do |
401 assert_equal @user, User.current | 428 assert_equal @user, User.current |
410 # | 437 # |
411 # @param [String] url Request | 438 # @param [String] url Request |
412 def self.should_respond_with_content_type_based_on_url(url) | 439 def self.should_respond_with_content_type_based_on_url(url) |
413 case | 440 case |
414 when url.match(/xml/i) | 441 when url.match(/xml/i) |
415 should_respond_with_content_type :xml | 442 should "respond with XML" do |
443 assert_equal 'application/xml', @response.content_type | |
444 end | |
416 when url.match(/json/i) | 445 when url.match(/json/i) |
417 should_respond_with_content_type :json | 446 should "respond with JSON" do |
447 assert_equal 'application/json', @response.content_type | |
448 end | |
418 else | 449 else |
419 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}" | 450 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}" |
420 end | 451 end |
421 | |
422 end | 452 end |
423 | 453 |
424 # Uses the url to assert which format the response should be in | 454 # Uses the url to assert which format the response should be in |
425 # | 455 # |
426 # '/project/issues.xml' => should_be_a_valid_xml_string | 456 # '/project/issues.xml' => should_be_a_valid_xml_string |
434 when url.match(/json/i) | 464 when url.match(/json/i) |
435 should_be_a_valid_json_string | 465 should_be_a_valid_json_string |
436 else | 466 else |
437 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}" | 467 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}" |
438 end | 468 end |
439 | |
440 end | 469 end |
441 | 470 |
442 # Checks that the response is a valid JSON string | 471 # Checks that the response is a valid JSON string |
443 def self.should_be_a_valid_json_string | 472 def self.should_be_a_valid_json_string |
444 should "be a valid JSON string (or empty)" do | 473 should "be a valid JSON string (or empty)" do |
451 should "be a valid XML string" do | 480 should "be a valid XML string" do |
452 assert REXML::Document.new(response.body) | 481 assert REXML::Document.new(response.body) |
453 end | 482 end |
454 end | 483 end |
455 | 484 |
485 def self.should_respond_with(status) | |
486 should "respond with #{status}" do | |
487 assert_response status | |
488 end | |
489 end | |
456 end | 490 end |
457 | 491 |
458 # Simple module to "namespace" all of the API tests | 492 # Simple module to "namespace" all of the API tests |
459 module ApiTest | 493 module ApiTest |
460 end | 494 end |