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