##// END OF EJS Templates
code format clean up escaped "can't" constant...
Toshi MARUYAMA -
r12508:31cab06f91fb
parent child
Show More
@@ -1,484 +1,484
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
2 # Copyright (C) 2006-2014 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 #require 'shoulda'
18 #require 'shoulda'
19 ENV["RAILS_ENV"] = "test"
19 ENV["RAILS_ENV"] = "test"
20 require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
20 require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
21 require 'rails/test_help'
21 require 'rails/test_help'
22 require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
22 require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
23
23
24 require File.expand_path(File.dirname(__FILE__) + '/object_helpers')
24 require File.expand_path(File.dirname(__FILE__) + '/object_helpers')
25 include ObjectHelpers
25 include ObjectHelpers
26
26
27 require 'awesome_nested_set/version'
27 require 'awesome_nested_set/version'
28
28
29 class ActiveSupport::TestCase
29 class ActiveSupport::TestCase
30 include ActionDispatch::TestProcess
30 include ActionDispatch::TestProcess
31
31
32 self.use_transactional_fixtures = true
32 self.use_transactional_fixtures = true
33 self.use_instantiated_fixtures = false
33 self.use_instantiated_fixtures = false
34
34
35 ESCAPED_CANT='can't'
35 ESCAPED_CANT = 'can't'
36 # Rails 4.0.2
36 # Rails 4.0.2
37 #ESCAPED_CANT='can't'
37 #ESCAPED_CANT = 'can't'
38
38
39 def log_user(login, password)
39 def log_user(login, password)
40 User.anonymous
40 User.anonymous
41 get "/login"
41 get "/login"
42 assert_equal nil, session[:user_id]
42 assert_equal nil, session[:user_id]
43 assert_response :success
43 assert_response :success
44 assert_template "account/login"
44 assert_template "account/login"
45 post "/login", :username => login, :password => password
45 post "/login", :username => login, :password => password
46 assert_equal login, User.find(session[:user_id]).login
46 assert_equal login, User.find(session[:user_id]).login
47 end
47 end
48
48
49 def uploaded_test_file(name, mime)
49 def uploaded_test_file(name, mime)
50 fixture_file_upload("files/#{name}", mime, true)
50 fixture_file_upload("files/#{name}", mime, true)
51 end
51 end
52
52
53 def credentials(user, password=nil)
53 def credentials(user, password=nil)
54 {'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
54 {'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
55 end
55 end
56
56
57 # Mock out a file
57 # Mock out a file
58 def self.mock_file
58 def self.mock_file
59 file = 'a_file.png'
59 file = 'a_file.png'
60 file.stubs(:size).returns(32)
60 file.stubs(:size).returns(32)
61 file.stubs(:original_filename).returns('a_file.png')
61 file.stubs(:original_filename).returns('a_file.png')
62 file.stubs(:content_type).returns('image/png')
62 file.stubs(:content_type).returns('image/png')
63 file.stubs(:read).returns(false)
63 file.stubs(:read).returns(false)
64 file
64 file
65 end
65 end
66
66
67 def mock_file
67 def mock_file
68 self.class.mock_file
68 self.class.mock_file
69 end
69 end
70
70
71 def mock_file_with_options(options={})
71 def mock_file_with_options(options={})
72 file = ''
72 file = ''
73 file.stubs(:size).returns(32)
73 file.stubs(:size).returns(32)
74 original_filename = options[:original_filename] || nil
74 original_filename = options[:original_filename] || nil
75 file.stubs(:original_filename).returns(original_filename)
75 file.stubs(:original_filename).returns(original_filename)
76 content_type = options[:content_type] || nil
76 content_type = options[:content_type] || nil
77 file.stubs(:content_type).returns(content_type)
77 file.stubs(:content_type).returns(content_type)
78 file.stubs(:read).returns(false)
78 file.stubs(:read).returns(false)
79 file
79 file
80 end
80 end
81
81
82 # Use a temporary directory for attachment related tests
82 # Use a temporary directory for attachment related tests
83 def set_tmp_attachments_directory
83 def set_tmp_attachments_directory
84 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
84 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
85 unless File.directory?("#{Rails.root}/tmp/test/attachments")
85 unless File.directory?("#{Rails.root}/tmp/test/attachments")
86 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
86 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
87 end
87 end
88 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
88 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
89 end
89 end
90
90
91 def set_fixtures_attachments_directory
91 def set_fixtures_attachments_directory
92 Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
92 Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
93 end
93 end
94
94
95 def with_settings(options, &block)
95 def with_settings(options, &block)
96 saved_settings = options.keys.inject({}) do |h, k|
96 saved_settings = options.keys.inject({}) do |h, k|
97 h[k] = case Setting[k]
97 h[k] = case Setting[k]
98 when Symbol, false, true, nil
98 when Symbol, false, true, nil
99 Setting[k]
99 Setting[k]
100 else
100 else
101 Setting[k].dup
101 Setting[k].dup
102 end
102 end
103 h
103 h
104 end
104 end
105 options.each {|k, v| Setting[k] = v}
105 options.each {|k, v| Setting[k] = v}
106 yield
106 yield
107 ensure
107 ensure
108 saved_settings.each {|k, v| Setting[k] = v} if saved_settings
108 saved_settings.each {|k, v| Setting[k] = v} if saved_settings
109 end
109 end
110
110
111 # Yields the block with user as the current user
111 # Yields the block with user as the current user
112 def with_current_user(user, &block)
112 def with_current_user(user, &block)
113 saved_user = User.current
113 saved_user = User.current
114 User.current = user
114 User.current = user
115 yield
115 yield
116 ensure
116 ensure
117 User.current = saved_user
117 User.current = saved_user
118 end
118 end
119
119
120 def change_user_password(login, new_password)
120 def change_user_password(login, new_password)
121 user = User.where(:login => login).first
121 user = User.where(:login => login).first
122 user.password, user.password_confirmation = new_password, new_password
122 user.password, user.password_confirmation = new_password, new_password
123 user.save!
123 user.save!
124 end
124 end
125
125
126 def self.ldap_configured?
126 def self.ldap_configured?
127 @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
127 @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
128 return @test_ldap.bind
128 return @test_ldap.bind
129 rescue Exception => e
129 rescue Exception => e
130 # LDAP is not listening
130 # LDAP is not listening
131 return nil
131 return nil
132 end
132 end
133
133
134 def self.convert_installed?
134 def self.convert_installed?
135 Redmine::Thumbnail.convert_available?
135 Redmine::Thumbnail.convert_available?
136 end
136 end
137
137
138 # Returns the path to the test +vendor+ repository
138 # Returns the path to the test +vendor+ repository
139 def self.repository_path(vendor)
139 def self.repository_path(vendor)
140 Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
140 Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
141 end
141 end
142
142
143 # Returns the url of the subversion test repository
143 # Returns the url of the subversion test repository
144 def self.subversion_repository_url
144 def self.subversion_repository_url
145 path = repository_path('subversion')
145 path = repository_path('subversion')
146 path = '/' + path unless path.starts_with?('/')
146 path = '/' + path unless path.starts_with?('/')
147 "file://#{path}"
147 "file://#{path}"
148 end
148 end
149
149
150 # Returns true if the +vendor+ test repository is configured
150 # Returns true if the +vendor+ test repository is configured
151 def self.repository_configured?(vendor)
151 def self.repository_configured?(vendor)
152 File.directory?(repository_path(vendor))
152 File.directory?(repository_path(vendor))
153 end
153 end
154
154
155 def repository_path_hash(arr)
155 def repository_path_hash(arr)
156 hs = {}
156 hs = {}
157 hs[:path] = arr.join("/")
157 hs[:path] = arr.join("/")
158 hs[:param] = arr.join("/")
158 hs[:param] = arr.join("/")
159 hs
159 hs
160 end
160 end
161
161
162 def assert_save(object)
162 def assert_save(object)
163 saved = object.save
163 saved = object.save
164 message = "#{object.class} could not be saved"
164 message = "#{object.class} could not be saved"
165 errors = object.errors.full_messages.map {|m| "- #{m}"}
165 errors = object.errors.full_messages.map {|m| "- #{m}"}
166 message << ":\n#{errors.join("\n")}" if errors.any?
166 message << ":\n#{errors.join("\n")}" if errors.any?
167 assert_equal true, saved, message
167 assert_equal true, saved, message
168 end
168 end
169
169
170 def assert_error_tag(options={})
170 def assert_error_tag(options={})
171 assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options))
171 assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options))
172 end
172 end
173
173
174 def assert_include(expected, s, message=nil)
174 def assert_include(expected, s, message=nil)
175 assert s.include?(expected), (message || "\"#{expected}\" not found in \"#{s}\"")
175 assert s.include?(expected), (message || "\"#{expected}\" not found in \"#{s}\"")
176 end
176 end
177
177
178 def assert_not_include(expected, s, message=nil)
178 def assert_not_include(expected, s, message=nil)
179 assert !s.include?(expected), (message || "\"#{expected}\" found in \"#{s}\"")
179 assert !s.include?(expected), (message || "\"#{expected}\" found in \"#{s}\"")
180 end
180 end
181
181
182 def assert_select_in(text, *args, &block)
182 def assert_select_in(text, *args, &block)
183 d = HTML::Document.new(CGI::unescapeHTML(String.new(text))).root
183 d = HTML::Document.new(CGI::unescapeHTML(String.new(text))).root
184 assert_select(d, *args, &block)
184 assert_select(d, *args, &block)
185 end
185 end
186
186
187 def assert_mail_body_match(expected, mail, message=nil)
187 def assert_mail_body_match(expected, mail, message=nil)
188 if expected.is_a?(String)
188 if expected.is_a?(String)
189 assert_include expected, mail_body(mail), message
189 assert_include expected, mail_body(mail), message
190 else
190 else
191 assert_match expected, mail_body(mail), message
191 assert_match expected, mail_body(mail), message
192 end
192 end
193 end
193 end
194
194
195 def assert_mail_body_no_match(expected, mail, message=nil)
195 def assert_mail_body_no_match(expected, mail, message=nil)
196 if expected.is_a?(String)
196 if expected.is_a?(String)
197 assert_not_include expected, mail_body(mail), message
197 assert_not_include expected, mail_body(mail), message
198 else
198 else
199 assert_no_match expected, mail_body(mail), message
199 assert_no_match expected, mail_body(mail), message
200 end
200 end
201 end
201 end
202
202
203 def mail_body(mail)
203 def mail_body(mail)
204 mail.parts.first.body.encoded
204 mail.parts.first.body.encoded
205 end
205 end
206
206
207 # awesome_nested_set new node lft and rgt value changed this refactor revision.
207 # awesome_nested_set new node lft and rgt value changed this refactor revision.
208 # https://github.com/collectiveidea/awesome_nested_set/commit/199fca9bb938e40200cd90714dc69247ef017c61
208 # https://github.com/collectiveidea/awesome_nested_set/commit/199fca9bb938e40200cd90714dc69247ef017c61
209 # The reason of behavior change is that "self.class.base_class.unscoped" was added to this line.
209 # The reason of behavior change is that "self.class.base_class.unscoped" was added to this line.
210 # https://github.com/collectiveidea/awesome_nested_set/commit/199fca9bb9#diff-f61b59a5e6319024e211b0ffdd0e4ef1R273
210 # https://github.com/collectiveidea/awesome_nested_set/commit/199fca9bb9#diff-f61b59a5e6319024e211b0ffdd0e4ef1R273
211 # It seems correct behavior because of this line comment.
211 # It seems correct behavior because of this line comment.
212 # https://github.com/collectiveidea/awesome_nested_set/blame/199fca9bb9/lib/awesome_nested_set/model.rb#L278
212 # https://github.com/collectiveidea/awesome_nested_set/blame/199fca9bb9/lib/awesome_nested_set/model.rb#L278
213 def new_issue_lft
213 def new_issue_lft
214 ::AwesomeNestedSet::VERSION > "2.1.6" ? Issue.maximum(:rgt) + 1 : 1
214 ::AwesomeNestedSet::VERSION > "2.1.6" ? Issue.maximum(:rgt) + 1 : 1
215 end
215 end
216 end
216 end
217
217
218 module Redmine
218 module Redmine
219 module ApiTest
219 module ApiTest
220 # Base class for API tests
220 # Base class for API tests
221 class Base < ActionDispatch::IntegrationTest
221 class Base < ActionDispatch::IntegrationTest
222 # Test that a request allows the three types of API authentication
222 # Test that a request allows the three types of API authentication
223 #
223 #
224 # * HTTP Basic with username and password
224 # * HTTP Basic with username and password
225 # * HTTP Basic with an api key for the username
225 # * HTTP Basic with an api key for the username
226 # * Key based with the key=X parameter
226 # * Key based with the key=X parameter
227 #
227 #
228 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
228 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
229 # @param [String] url the request url
229 # @param [String] url the request url
230 # @param [optional, Hash] parameters additional request parameters
230 # @param [optional, Hash] parameters additional request parameters
231 # @param [optional, Hash] options additional options
231 # @param [optional, Hash] options additional options
232 # @option options [Symbol] :success_code Successful response code (:success)
232 # @option options [Symbol] :success_code Successful response code (:success)
233 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
233 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
234 def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
234 def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
235 should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options)
235 should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options)
236 should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
236 should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
237 should_allow_key_based_auth(http_method, url, parameters, options)
237 should_allow_key_based_auth(http_method, url, parameters, options)
238 end
238 end
239
239
240 # Test that a request allows the username and password for HTTP BASIC
240 # Test that a request allows the username and password for HTTP BASIC
241 #
241 #
242 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
242 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
243 # @param [String] url the request url
243 # @param [String] url the request url
244 # @param [optional, Hash] parameters additional request parameters
244 # @param [optional, Hash] parameters additional request parameters
245 # @param [optional, Hash] options additional options
245 # @param [optional, Hash] options additional options
246 # @option options [Symbol] :success_code Successful response code (:success)
246 # @option options [Symbol] :success_code Successful response code (:success)
247 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
247 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
248 def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
248 def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
249 success_code = options[:success_code] || :success
249 success_code = options[:success_code] || :success
250 failure_code = options[:failure_code] || :unauthorized
250 failure_code = options[:failure_code] || :unauthorized
251
251
252 context "should allow http basic auth using a username and password for #{http_method} #{url}" do
252 context "should allow http basic auth using a username and password for #{http_method} #{url}" do
253 context "with a valid HTTP authentication" do
253 context "with a valid HTTP authentication" do
254 setup do
254 setup do
255 @user = User.generate! do |user|
255 @user = User.generate! do |user|
256 user.admin = true
256 user.admin = true
257 user.password = 'my_password'
257 user.password = 'my_password'
258 end
258 end
259 send(http_method, url, parameters, credentials(@user.login, 'my_password'))
259 send(http_method, url, parameters, credentials(@user.login, 'my_password'))
260 end
260 end
261
261
262 should_respond_with success_code
262 should_respond_with success_code
263 should_respond_with_content_type_based_on_url(url)
263 should_respond_with_content_type_based_on_url(url)
264 should "login as the user" do
264 should "login as the user" do
265 assert_equal @user, User.current
265 assert_equal @user, User.current
266 end
266 end
267 end
267 end
268
268
269 context "with an invalid HTTP authentication" do
269 context "with an invalid HTTP authentication" do
270 setup do
270 setup do
271 @user = User.generate!
271 @user = User.generate!
272 send(http_method, url, parameters, credentials(@user.login, 'wrong_password'))
272 send(http_method, url, parameters, credentials(@user.login, 'wrong_password'))
273 end
273 end
274
274
275 should_respond_with failure_code
275 should_respond_with failure_code
276 should_respond_with_content_type_based_on_url(url)
276 should_respond_with_content_type_based_on_url(url)
277 should "not login as the user" do
277 should "not login as the user" do
278 assert_equal User.anonymous, User.current
278 assert_equal User.anonymous, User.current
279 end
279 end
280 end
280 end
281
281
282 context "without credentials" do
282 context "without credentials" do
283 setup do
283 setup do
284 send(http_method, url, parameters)
284 send(http_method, url, parameters)
285 end
285 end
286
286
287 should_respond_with failure_code
287 should_respond_with failure_code
288 should_respond_with_content_type_based_on_url(url)
288 should_respond_with_content_type_based_on_url(url)
289 should "include_www_authenticate_header" do
289 should "include_www_authenticate_header" do
290 assert @controller.response.headers.has_key?('WWW-Authenticate')
290 assert @controller.response.headers.has_key?('WWW-Authenticate')
291 end
291 end
292 end
292 end
293 end
293 end
294 end
294 end
295
295
296 # Test that a request allows the API key with HTTP BASIC
296 # Test that a request allows the API key with HTTP BASIC
297 #
297 #
298 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
298 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
299 # @param [String] url the request url
299 # @param [String] url the request url
300 # @param [optional, Hash] parameters additional request parameters
300 # @param [optional, Hash] parameters additional request parameters
301 # @param [optional, Hash] options additional options
301 # @param [optional, Hash] options additional options
302 # @option options [Symbol] :success_code Successful response code (:success)
302 # @option options [Symbol] :success_code Successful response code (:success)
303 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
303 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
304 def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
304 def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
305 success_code = options[:success_code] || :success
305 success_code = options[:success_code] || :success
306 failure_code = options[:failure_code] || :unauthorized
306 failure_code = options[:failure_code] || :unauthorized
307
307
308 context "should allow http basic auth with a key for #{http_method} #{url}" do
308 context "should allow http basic auth with a key for #{http_method} #{url}" do
309 context "with a valid HTTP authentication using the API token" do
309 context "with a valid HTTP authentication using the API token" do
310 setup do
310 setup do
311 @user = User.generate! do |user|
311 @user = User.generate! do |user|
312 user.admin = true
312 user.admin = true
313 end
313 end
314 @token = Token.create!(:user => @user, :action => 'api')
314 @token = Token.create!(:user => @user, :action => 'api')
315 send(http_method, url, parameters, credentials(@token.value, 'X'))
315 send(http_method, url, parameters, credentials(@token.value, 'X'))
316 end
316 end
317 should_respond_with success_code
317 should_respond_with success_code
318 should_respond_with_content_type_based_on_url(url)
318 should_respond_with_content_type_based_on_url(url)
319 should_be_a_valid_response_string_based_on_url(url)
319 should_be_a_valid_response_string_based_on_url(url)
320 should "login as the user" do
320 should "login as the user" do
321 assert_equal @user, User.current
321 assert_equal @user, User.current
322 end
322 end
323 end
323 end
324
324
325 context "with an invalid HTTP authentication" do
325 context "with an invalid HTTP authentication" do
326 setup do
326 setup do
327 @user = User.generate!
327 @user = User.generate!
328 @token = Token.create!(:user => @user, :action => 'feeds')
328 @token = Token.create!(:user => @user, :action => 'feeds')
329 send(http_method, url, parameters, credentials(@token.value, 'X'))
329 send(http_method, url, parameters, credentials(@token.value, 'X'))
330 end
330 end
331 should_respond_with failure_code
331 should_respond_with failure_code
332 should_respond_with_content_type_based_on_url(url)
332 should_respond_with_content_type_based_on_url(url)
333 should "not login as the user" do
333 should "not login as the user" do
334 assert_equal User.anonymous, User.current
334 assert_equal User.anonymous, User.current
335 end
335 end
336 end
336 end
337 end
337 end
338 end
338 end
339
339
340 # Test that a request allows full key authentication
340 # Test that a request allows full key authentication
341 #
341 #
342 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
342 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
343 # @param [String] url the request url, without the key=ZXY parameter
343 # @param [String] url the request url, without the key=ZXY parameter
344 # @param [optional, Hash] parameters additional request parameters
344 # @param [optional, Hash] parameters additional request parameters
345 # @param [optional, Hash] options additional options
345 # @param [optional, Hash] options additional options
346 # @option options [Symbol] :success_code Successful response code (:success)
346 # @option options [Symbol] :success_code Successful response code (:success)
347 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
347 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
348 def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
348 def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
349 success_code = options[:success_code] || :success
349 success_code = options[:success_code] || :success
350 failure_code = options[:failure_code] || :unauthorized
350 failure_code = options[:failure_code] || :unauthorized
351
351
352 context "should allow key based auth using key=X for #{http_method} #{url}" do
352 context "should allow key based auth using key=X for #{http_method} #{url}" do
353 context "with a valid api token" do
353 context "with a valid api token" do
354 setup do
354 setup do
355 @user = User.generate! do |user|
355 @user = User.generate! do |user|
356 user.admin = true
356 user.admin = true
357 end
357 end
358 @token = Token.create!(:user => @user, :action => 'api')
358 @token = Token.create!(:user => @user, :action => 'api')
359 # Simple url parse to add on ?key= or &key=
359 # Simple url parse to add on ?key= or &key=
360 request_url = if url.match(/\?/)
360 request_url = if url.match(/\?/)
361 url + "&key=#{@token.value}"
361 url + "&key=#{@token.value}"
362 else
362 else
363 url + "?key=#{@token.value}"
363 url + "?key=#{@token.value}"
364 end
364 end
365 send(http_method, request_url, parameters)
365 send(http_method, request_url, parameters)
366 end
366 end
367 should_respond_with success_code
367 should_respond_with success_code
368 should_respond_with_content_type_based_on_url(url)
368 should_respond_with_content_type_based_on_url(url)
369 should_be_a_valid_response_string_based_on_url(url)
369 should_be_a_valid_response_string_based_on_url(url)
370 should "login as the user" do
370 should "login as the user" do
371 assert_equal @user, User.current
371 assert_equal @user, User.current
372 end
372 end
373 end
373 end
374
374
375 context "with an invalid api token" do
375 context "with an invalid api token" do
376 setup do
376 setup do
377 @user = User.generate! do |user|
377 @user = User.generate! do |user|
378 user.admin = true
378 user.admin = true
379 end
379 end
380 @token = Token.create!(:user => @user, :action => 'feeds')
380 @token = Token.create!(:user => @user, :action => 'feeds')
381 # Simple url parse to add on ?key= or &key=
381 # Simple url parse to add on ?key= or &key=
382 request_url = if url.match(/\?/)
382 request_url = if url.match(/\?/)
383 url + "&key=#{@token.value}"
383 url + "&key=#{@token.value}"
384 else
384 else
385 url + "?key=#{@token.value}"
385 url + "?key=#{@token.value}"
386 end
386 end
387 send(http_method, request_url, parameters)
387 send(http_method, request_url, parameters)
388 end
388 end
389 should_respond_with failure_code
389 should_respond_with failure_code
390 should_respond_with_content_type_based_on_url(url)
390 should_respond_with_content_type_based_on_url(url)
391 should "not login as the user" do
391 should "not login as the user" do
392 assert_equal User.anonymous, User.current
392 assert_equal User.anonymous, User.current
393 end
393 end
394 end
394 end
395 end
395 end
396
396
397 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
397 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
398 setup do
398 setup do
399 @user = User.generate! do |user|
399 @user = User.generate! do |user|
400 user.admin = true
400 user.admin = true
401 end
401 end
402 @token = Token.create!(:user => @user, :action => 'api')
402 @token = Token.create!(:user => @user, :action => 'api')
403 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
403 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
404 end
404 end
405 should_respond_with success_code
405 should_respond_with success_code
406 should_respond_with_content_type_based_on_url(url)
406 should_respond_with_content_type_based_on_url(url)
407 should_be_a_valid_response_string_based_on_url(url)
407 should_be_a_valid_response_string_based_on_url(url)
408 should "login as the user" do
408 should "login as the user" do
409 assert_equal @user, User.current
409 assert_equal @user, User.current
410 end
410 end
411 end
411 end
412 end
412 end
413
413
414 # Uses should_respond_with_content_type based on what's in the url:
414 # Uses should_respond_with_content_type based on what's in the url:
415 #
415 #
416 # '/project/issues.xml' => should_respond_with_content_type :xml
416 # '/project/issues.xml' => should_respond_with_content_type :xml
417 # '/project/issues.json' => should_respond_with_content_type :json
417 # '/project/issues.json' => should_respond_with_content_type :json
418 #
418 #
419 # @param [String] url Request
419 # @param [String] url Request
420 def self.should_respond_with_content_type_based_on_url(url)
420 def self.should_respond_with_content_type_based_on_url(url)
421 case
421 case
422 when url.match(/xml/i)
422 when url.match(/xml/i)
423 should "respond with XML" do
423 should "respond with XML" do
424 assert_equal 'application/xml', @response.content_type
424 assert_equal 'application/xml', @response.content_type
425 end
425 end
426 when url.match(/json/i)
426 when url.match(/json/i)
427 should "respond with JSON" do
427 should "respond with JSON" do
428 assert_equal 'application/json', @response.content_type
428 assert_equal 'application/json', @response.content_type
429 end
429 end
430 else
430 else
431 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
431 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
432 end
432 end
433 end
433 end
434
434
435 # Uses the url to assert which format the response should be in
435 # Uses the url to assert which format the response should be in
436 #
436 #
437 # '/project/issues.xml' => should_be_a_valid_xml_string
437 # '/project/issues.xml' => should_be_a_valid_xml_string
438 # '/project/issues.json' => should_be_a_valid_json_string
438 # '/project/issues.json' => should_be_a_valid_json_string
439 #
439 #
440 # @param [String] url Request
440 # @param [String] url Request
441 def self.should_be_a_valid_response_string_based_on_url(url)
441 def self.should_be_a_valid_response_string_based_on_url(url)
442 case
442 case
443 when url.match(/xml/i)
443 when url.match(/xml/i)
444 should_be_a_valid_xml_string
444 should_be_a_valid_xml_string
445 when url.match(/json/i)
445 when url.match(/json/i)
446 should_be_a_valid_json_string
446 should_be_a_valid_json_string
447 else
447 else
448 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
448 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
449 end
449 end
450 end
450 end
451
451
452 # Checks that the response is a valid JSON string
452 # Checks that the response is a valid JSON string
453 def self.should_be_a_valid_json_string
453 def self.should_be_a_valid_json_string
454 should "be a valid JSON string (or empty)" do
454 should "be a valid JSON string (or empty)" do
455 assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
455 assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
456 end
456 end
457 end
457 end
458
458
459 # Checks that the response is a valid XML string
459 # Checks that the response is a valid XML string
460 def self.should_be_a_valid_xml_string
460 def self.should_be_a_valid_xml_string
461 should "be a valid XML string" do
461 should "be a valid XML string" do
462 assert REXML::Document.new(response.body)
462 assert REXML::Document.new(response.body)
463 end
463 end
464 end
464 end
465
465
466 def self.should_respond_with(status)
466 def self.should_respond_with(status)
467 should "respond with #{status}" do
467 should "respond with #{status}" do
468 assert_response status
468 assert_response status
469 end
469 end
470 end
470 end
471 end
471 end
472 end
472 end
473 end
473 end
474
474
475 # URL helpers do not work with config.threadsafe!
475 # URL helpers do not work with config.threadsafe!
476 # https://github.com/rspec/rspec-rails/issues/476#issuecomment-4705454
476 # https://github.com/rspec/rspec-rails/issues/476#issuecomment-4705454
477 ActionView::TestCase::TestController.instance_eval do
477 ActionView::TestCase::TestController.instance_eval do
478 helper Rails.application.routes.url_helpers
478 helper Rails.application.routes.url_helpers
479 end
479 end
480 ActionView::TestCase::TestController.class_eval do
480 ActionView::TestCase::TestController.class_eval do
481 def _routes
481 def _routes
482 Rails.application.routes
482 Rails.application.routes
483 end
483 end
484 end
484 end
General Comments 0
You need to be logged in to leave comments. Login now