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