##// END OF EJS Templates
replace RAILS_ROOT to Rails.root at test/test_helper.rb....
Toshi MARUYAMA -
r5983:e4d082a42194
parent child
Show More
@@ -1,444 +1,444
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 File.join(RAILS_ROOT,'test', 'mocks', 'open_id_authentication_mock.rb')
22 require File.join(RAILS_ROOT,'test', 'mocks', 'open_id_authentication_mock.rb')
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 File.join(RAILS_ROOT.gsub(%r{config\/\.\.}, ''), "/tmp/test/#{vendor.downcase}_repository")
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 # Shoulda macros
131 # Shoulda macros
132 def self.should_render_404
132 def self.should_render_404
133 should_respond_with :not_found
133 should_respond_with :not_found
134 should_render_template 'common/error'
134 should_render_template 'common/error'
135 end
135 end
136
136
137 def self.should_have_before_filter(expected_method, options = {})
137 def self.should_have_before_filter(expected_method, options = {})
138 should_have_filter('before', expected_method, options)
138 should_have_filter('before', expected_method, options)
139 end
139 end
140
140
141 def self.should_have_after_filter(expected_method, options = {})
141 def self.should_have_after_filter(expected_method, options = {})
142 should_have_filter('after', expected_method, options)
142 should_have_filter('after', expected_method, options)
143 end
143 end
144
144
145 def self.should_have_filter(filter_type, expected_method, options)
145 def self.should_have_filter(filter_type, expected_method, options)
146 description = "have #{filter_type}_filter :#{expected_method}"
146 description = "have #{filter_type}_filter :#{expected_method}"
147 description << " with #{options.inspect}" unless options.empty?
147 description << " with #{options.inspect}" unless options.empty?
148
148
149 should description do
149 should description do
150 klass = "action_controller/filters/#{filter_type}_filter".classify.constantize
150 klass = "action_controller/filters/#{filter_type}_filter".classify.constantize
151 expected = klass.new(:filter, expected_method.to_sym, options)
151 expected = klass.new(:filter, expected_method.to_sym, options)
152 assert_equal 1, @controller.class.filter_chain.select { |filter|
152 assert_equal 1, @controller.class.filter_chain.select { |filter|
153 filter.method == expected.method && filter.kind == expected.kind &&
153 filter.method == expected.method && filter.kind == expected.kind &&
154 filter.options == expected.options && filter.class == expected.class
154 filter.options == expected.options && filter.class == expected.class
155 }.size
155 }.size
156 end
156 end
157 end
157 end
158
158
159 def self.should_show_the_old_and_new_values_for(prop_key, model, &block)
159 def self.should_show_the_old_and_new_values_for(prop_key, model, &block)
160 context "" do
160 context "" do
161 setup do
161 setup do
162 if block_given?
162 if block_given?
163 instance_eval &block
163 instance_eval &block
164 else
164 else
165 @old_value = model.generate!
165 @old_value = model.generate!
166 @new_value = model.generate!
166 @new_value = model.generate!
167 end
167 end
168 end
168 end
169
169
170 should "use the new value's name" do
170 should "use the new value's name" do
171 @detail = JournalDetail.generate!(:property => 'attr',
171 @detail = JournalDetail.generate!(:property => 'attr',
172 :old_value => @old_value.id,
172 :old_value => @old_value.id,
173 :value => @new_value.id,
173 :value => @new_value.id,
174 :prop_key => prop_key)
174 :prop_key => prop_key)
175
175
176 assert_match @new_value.name, show_detail(@detail, true)
176 assert_match @new_value.name, show_detail(@detail, true)
177 end
177 end
178
178
179 should "use the old value's name" do
179 should "use the old value's name" do
180 @detail = JournalDetail.generate!(:property => 'attr',
180 @detail = JournalDetail.generate!(:property => 'attr',
181 :old_value => @old_value.id,
181 :old_value => @old_value.id,
182 :value => @new_value.id,
182 :value => @new_value.id,
183 :prop_key => prop_key)
183 :prop_key => prop_key)
184
184
185 assert_match @old_value.name, show_detail(@detail, true)
185 assert_match @old_value.name, show_detail(@detail, true)
186 end
186 end
187 end
187 end
188 end
188 end
189
189
190 def self.should_create_a_new_user(&block)
190 def self.should_create_a_new_user(&block)
191 should "create a new user" do
191 should "create a new user" do
192 user = instance_eval &block
192 user = instance_eval &block
193 assert user
193 assert user
194 assert_kind_of User, user
194 assert_kind_of User, user
195 assert !user.new_record?
195 assert !user.new_record?
196 end
196 end
197 end
197 end
198
198
199 # Test that a request allows the three types of API authentication
199 # Test that a request allows the three types of API authentication
200 #
200 #
201 # * HTTP Basic with username and password
201 # * HTTP Basic with username and password
202 # * HTTP Basic with an api key for the username
202 # * HTTP Basic with an api key for the username
203 # * Key based with the key=X parameter
203 # * Key based with the key=X parameter
204 #
204 #
205 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
205 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
206 # @param [String] url the request url
206 # @param [String] url the request url
207 # @param [optional, Hash] parameters additional request parameters
207 # @param [optional, Hash] parameters additional request parameters
208 # @param [optional, Hash] options additional options
208 # @param [optional, Hash] options additional options
209 # @option options [Symbol] :success_code Successful response code (:success)
209 # @option options [Symbol] :success_code Successful response code (:success)
210 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
210 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
211 def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
211 def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
212 should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options)
212 should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options)
213 should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
213 should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
214 should_allow_key_based_auth(http_method, url, parameters, options)
214 should_allow_key_based_auth(http_method, url, parameters, options)
215 end
215 end
216
216
217 # Test that a request allows the username and password for HTTP BASIC
217 # Test that a request allows the username and password for HTTP BASIC
218 #
218 #
219 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
219 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
220 # @param [String] url the request url
220 # @param [String] url the request url
221 # @param [optional, Hash] parameters additional request parameters
221 # @param [optional, Hash] parameters additional request parameters
222 # @param [optional, Hash] options additional options
222 # @param [optional, Hash] options additional options
223 # @option options [Symbol] :success_code Successful response code (:success)
223 # @option options [Symbol] :success_code Successful response code (:success)
224 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
224 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
225 def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
225 def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
226 success_code = options[:success_code] || :success
226 success_code = options[:success_code] || :success
227 failure_code = options[:failure_code] || :unauthorized
227 failure_code = options[:failure_code] || :unauthorized
228
228
229 context "should allow http basic auth using a username and password for #{http_method} #{url}" do
229 context "should allow http basic auth using a username and password for #{http_method} #{url}" do
230 context "with a valid HTTP authentication" do
230 context "with a valid HTTP authentication" do
231 setup do
231 setup do
232 @user = User.generate_with_protected!(:password => 'my_password', :password_confirmation => 'my_password', :admin => true) # Admin so they can access the project
232 @user = User.generate_with_protected!(:password => 'my_password', :password_confirmation => 'my_password', :admin => true) # Admin so they can access the project
233 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@user.login, 'my_password')
233 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@user.login, 'my_password')
234 send(http_method, url, parameters, {:authorization => @authorization})
234 send(http_method, url, parameters, {:authorization => @authorization})
235 end
235 end
236
236
237 should_respond_with success_code
237 should_respond_with success_code
238 should_respond_with_content_type_based_on_url(url)
238 should_respond_with_content_type_based_on_url(url)
239 should "login as the user" do
239 should "login as the user" do
240 assert_equal @user, User.current
240 assert_equal @user, User.current
241 end
241 end
242 end
242 end
243
243
244 context "with an invalid HTTP authentication" do
244 context "with an invalid HTTP authentication" do
245 setup do
245 setup do
246 @user = User.generate_with_protected!
246 @user = User.generate_with_protected!
247 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@user.login, 'wrong_password')
247 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@user.login, 'wrong_password')
248 send(http_method, url, parameters, {:authorization => @authorization})
248 send(http_method, url, parameters, {:authorization => @authorization})
249 end
249 end
250
250
251 should_respond_with failure_code
251 should_respond_with failure_code
252 should_respond_with_content_type_based_on_url(url)
252 should_respond_with_content_type_based_on_url(url)
253 should "not login as the user" do
253 should "not login as the user" do
254 assert_equal User.anonymous, User.current
254 assert_equal User.anonymous, User.current
255 end
255 end
256 end
256 end
257
257
258 context "without credentials" do
258 context "without credentials" do
259 setup do
259 setup do
260 send(http_method, url, parameters, {:authorization => ''})
260 send(http_method, url, parameters, {:authorization => ''})
261 end
261 end
262
262
263 should_respond_with failure_code
263 should_respond_with failure_code
264 should_respond_with_content_type_based_on_url(url)
264 should_respond_with_content_type_based_on_url(url)
265 should "include_www_authenticate_header" do
265 should "include_www_authenticate_header" do
266 assert @controller.response.headers.has_key?('WWW-Authenticate')
266 assert @controller.response.headers.has_key?('WWW-Authenticate')
267 end
267 end
268 end
268 end
269 end
269 end
270
270
271 end
271 end
272
272
273 # Test that a request allows the API key with HTTP BASIC
273 # Test that a request allows the API key with HTTP BASIC
274 #
274 #
275 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
275 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
276 # @param [String] url the request url
276 # @param [String] url the request url
277 # @param [optional, Hash] parameters additional request parameters
277 # @param [optional, Hash] parameters additional request parameters
278 # @param [optional, Hash] options additional options
278 # @param [optional, Hash] options additional options
279 # @option options [Symbol] :success_code Successful response code (:success)
279 # @option options [Symbol] :success_code Successful response code (:success)
280 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
280 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
281 def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
281 def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
282 success_code = options[:success_code] || :success
282 success_code = options[:success_code] || :success
283 failure_code = options[:failure_code] || :unauthorized
283 failure_code = options[:failure_code] || :unauthorized
284
284
285 context "should allow http basic auth with a key for #{http_method} #{url}" do
285 context "should allow http basic auth with a key for #{http_method} #{url}" do
286 context "with a valid HTTP authentication using the API token" do
286 context "with a valid HTTP authentication using the API token" do
287 setup do
287 setup do
288 @user = User.generate_with_protected!(:admin => true)
288 @user = User.generate_with_protected!(:admin => true)
289 @token = Token.generate!(:user => @user, :action => 'api')
289 @token = Token.generate!(:user => @user, :action => 'api')
290 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X')
290 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X')
291 send(http_method, url, parameters, {:authorization => @authorization})
291 send(http_method, url, parameters, {:authorization => @authorization})
292 end
292 end
293
293
294 should_respond_with success_code
294 should_respond_with success_code
295 should_respond_with_content_type_based_on_url(url)
295 should_respond_with_content_type_based_on_url(url)
296 should_be_a_valid_response_string_based_on_url(url)
296 should_be_a_valid_response_string_based_on_url(url)
297 should "login as the user" do
297 should "login as the user" do
298 assert_equal @user, User.current
298 assert_equal @user, User.current
299 end
299 end
300 end
300 end
301
301
302 context "with an invalid HTTP authentication" do
302 context "with an invalid HTTP authentication" do
303 setup do
303 setup do
304 @user = User.generate_with_protected!
304 @user = User.generate_with_protected!
305 @token = Token.generate!(:user => @user, :action => 'feeds')
305 @token = Token.generate!(:user => @user, :action => 'feeds')
306 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X')
306 @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X')
307 send(http_method, url, parameters, {:authorization => @authorization})
307 send(http_method, url, parameters, {:authorization => @authorization})
308 end
308 end
309
309
310 should_respond_with failure_code
310 should_respond_with failure_code
311 should_respond_with_content_type_based_on_url(url)
311 should_respond_with_content_type_based_on_url(url)
312 should "not login as the user" do
312 should "not login as the user" do
313 assert_equal User.anonymous, User.current
313 assert_equal User.anonymous, User.current
314 end
314 end
315 end
315 end
316 end
316 end
317 end
317 end
318
318
319 # Test that a request allows full key authentication
319 # Test that a request allows full key authentication
320 #
320 #
321 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
321 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
322 # @param [String] url the request url, without the key=ZXY parameter
322 # @param [String] url the request url, without the key=ZXY parameter
323 # @param [optional, Hash] parameters additional request parameters
323 # @param [optional, Hash] parameters additional request parameters
324 # @param [optional, Hash] options additional options
324 # @param [optional, Hash] options additional options
325 # @option options [Symbol] :success_code Successful response code (:success)
325 # @option options [Symbol] :success_code Successful response code (:success)
326 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
326 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
327 def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
327 def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
328 success_code = options[:success_code] || :success
328 success_code = options[:success_code] || :success
329 failure_code = options[:failure_code] || :unauthorized
329 failure_code = options[:failure_code] || :unauthorized
330
330
331 context "should allow key based auth using key=X for #{http_method} #{url}" do
331 context "should allow key based auth using key=X for #{http_method} #{url}" do
332 context "with a valid api token" do
332 context "with a valid api token" do
333 setup do
333 setup do
334 @user = User.generate_with_protected!(:admin => true)
334 @user = User.generate_with_protected!(:admin => true)
335 @token = Token.generate!(:user => @user, :action => 'api')
335 @token = Token.generate!(:user => @user, :action => 'api')
336 # Simple url parse to add on ?key= or &key=
336 # Simple url parse to add on ?key= or &key=
337 request_url = if url.match(/\?/)
337 request_url = if url.match(/\?/)
338 url + "&key=#{@token.value}"
338 url + "&key=#{@token.value}"
339 else
339 else
340 url + "?key=#{@token.value}"
340 url + "?key=#{@token.value}"
341 end
341 end
342 send(http_method, request_url, parameters)
342 send(http_method, request_url, parameters)
343 end
343 end
344
344
345 should_respond_with success_code
345 should_respond_with success_code
346 should_respond_with_content_type_based_on_url(url)
346 should_respond_with_content_type_based_on_url(url)
347 should_be_a_valid_response_string_based_on_url(url)
347 should_be_a_valid_response_string_based_on_url(url)
348 should "login as the user" do
348 should "login as the user" do
349 assert_equal @user, User.current
349 assert_equal @user, User.current
350 end
350 end
351 end
351 end
352
352
353 context "with an invalid api token" do
353 context "with an invalid api token" do
354 setup do
354 setup do
355 @user = User.generate_with_protected!
355 @user = User.generate_with_protected!
356 @token = Token.generate!(:user => @user, :action => 'feeds')
356 @token = Token.generate!(:user => @user, :action => 'feeds')
357 # Simple url parse to add on ?key= or &key=
357 # Simple url parse to add on ?key= or &key=
358 request_url = if url.match(/\?/)
358 request_url = if url.match(/\?/)
359 url + "&key=#{@token.value}"
359 url + "&key=#{@token.value}"
360 else
360 else
361 url + "?key=#{@token.value}"
361 url + "?key=#{@token.value}"
362 end
362 end
363 send(http_method, request_url, parameters)
363 send(http_method, request_url, parameters)
364 end
364 end
365
365
366 should_respond_with failure_code
366 should_respond_with failure_code
367 should_respond_with_content_type_based_on_url(url)
367 should_respond_with_content_type_based_on_url(url)
368 should "not login as the user" do
368 should "not login as the user" do
369 assert_equal User.anonymous, User.current
369 assert_equal User.anonymous, User.current
370 end
370 end
371 end
371 end
372 end
372 end
373
373
374 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
374 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
375 setup do
375 setup do
376 @user = User.generate_with_protected!(:admin => true)
376 @user = User.generate_with_protected!(:admin => true)
377 @token = Token.generate!(:user => @user, :action => 'api')
377 @token = Token.generate!(:user => @user, :action => 'api')
378 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
378 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
379 end
379 end
380
380
381 should_respond_with success_code
381 should_respond_with success_code
382 should_respond_with_content_type_based_on_url(url)
382 should_respond_with_content_type_based_on_url(url)
383 should_be_a_valid_response_string_based_on_url(url)
383 should_be_a_valid_response_string_based_on_url(url)
384 should "login as the user" do
384 should "login as the user" do
385 assert_equal @user, User.current
385 assert_equal @user, User.current
386 end
386 end
387 end
387 end
388 end
388 end
389
389
390 # Uses should_respond_with_content_type based on what's in the url:
390 # Uses should_respond_with_content_type based on what's in the url:
391 #
391 #
392 # '/project/issues.xml' => should_respond_with_content_type :xml
392 # '/project/issues.xml' => should_respond_with_content_type :xml
393 # '/project/issues.json' => should_respond_with_content_type :json
393 # '/project/issues.json' => should_respond_with_content_type :json
394 #
394 #
395 # @param [String] url Request
395 # @param [String] url Request
396 def self.should_respond_with_content_type_based_on_url(url)
396 def self.should_respond_with_content_type_based_on_url(url)
397 case
397 case
398 when url.match(/xml/i)
398 when url.match(/xml/i)
399 should_respond_with_content_type :xml
399 should_respond_with_content_type :xml
400 when url.match(/json/i)
400 when url.match(/json/i)
401 should_respond_with_content_type :json
401 should_respond_with_content_type :json
402 else
402 else
403 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
403 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
404 end
404 end
405
405
406 end
406 end
407
407
408 # Uses the url to assert which format the response should be in
408 # Uses the url to assert which format the response should be in
409 #
409 #
410 # '/project/issues.xml' => should_be_a_valid_xml_string
410 # '/project/issues.xml' => should_be_a_valid_xml_string
411 # '/project/issues.json' => should_be_a_valid_json_string
411 # '/project/issues.json' => should_be_a_valid_json_string
412 #
412 #
413 # @param [String] url Request
413 # @param [String] url Request
414 def self.should_be_a_valid_response_string_based_on_url(url)
414 def self.should_be_a_valid_response_string_based_on_url(url)
415 case
415 case
416 when url.match(/xml/i)
416 when url.match(/xml/i)
417 should_be_a_valid_xml_string
417 should_be_a_valid_xml_string
418 when url.match(/json/i)
418 when url.match(/json/i)
419 should_be_a_valid_json_string
419 should_be_a_valid_json_string
420 else
420 else
421 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
421 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
422 end
422 end
423
423
424 end
424 end
425
425
426 # Checks that the response is a valid JSON string
426 # Checks that the response is a valid JSON string
427 def self.should_be_a_valid_json_string
427 def self.should_be_a_valid_json_string
428 should "be a valid JSON string (or empty)" do
428 should "be a valid JSON string (or empty)" do
429 assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
429 assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
430 end
430 end
431 end
431 end
432
432
433 # Checks that the response is a valid XML string
433 # Checks that the response is a valid XML string
434 def self.should_be_a_valid_xml_string
434 def self.should_be_a_valid_xml_string
435 should "be a valid XML string" do
435 should "be a valid XML string" do
436 assert REXML::Document.new(response.body)
436 assert REXML::Document.new(response.body)
437 end
437 end
438 end
438 end
439
439
440 end
440 end
441
441
442 # Simple module to "namespace" all of the API tests
442 # Simple module to "namespace" all of the API tests
443 module ApiTest
443 module ApiTest
444 end
444 end
General Comments 0
You need to be logged in to leave comments. Login now