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