##// END OF EJS Templates
Renamed object_daddy_helper and removed exemplars....
Jean-Philippe Lang -
r9336:95f9246a46de
parent child
Show More
@@ -1,124 +1,124
1 module ObjectDaddyHelpers
1 module ObjectHelpers
2 # TODO: Remove these three once everyone has ported their code to use the
2 # TODO: Remove these three once everyone has ported their code to use the
3 # new object_daddy version with protected attribute support
3 # new object_daddy version with protected attribute support
4 def User.generate_with_protected(attributes={})
4 def User.generate_with_protected(attributes={})
5 User.generate(attributes)
5 User.generate(attributes)
6 end
6 end
7
7
8 def User.generate_with_protected!(attributes={})
8 def User.generate_with_protected!(attributes={})
9 User.generate!(attributes)
9 User.generate!(attributes)
10 end
10 end
11
11
12 def User.spawn_with_protected(attributes={})
12 def User.spawn_with_protected(attributes={})
13 User.spawn(attributes)
13 User.spawn(attributes)
14 end
14 end
15
15
16 def User.add_to_project(user, project, roles)
16 def User.add_to_project(user, project, roles)
17 roles = [roles] unless roles.is_a?(Array)
17 roles = [roles] unless roles.is_a?(Array)
18 Member.create!(:principal => user, :project => project, :roles => roles)
18 Member.create!(:principal => user, :project => project, :roles => roles)
19 end
19 end
20
20
21 def User.generate!(attributes={})
21 def User.generate!(attributes={})
22 @generated_user_login ||= 'user0'
22 @generated_user_login ||= 'user0'
23 @generated_user_login.succ!
23 @generated_user_login.succ!
24 user = User.new(attributes)
24 user = User.new(attributes)
25 user.login = @generated_user_login if user.login.blank?
25 user.login = @generated_user_login if user.login.blank?
26 user.mail = "#{@generated_user_login}@example.com" if user.mail.blank?
26 user.mail = "#{@generated_user_login}@example.com" if user.mail.blank?
27 user.firstname = "Bob" if user.firstname.blank?
27 user.firstname = "Bob" if user.firstname.blank?
28 user.lastname = "Doe" if user.lastname.blank?
28 user.lastname = "Doe" if user.lastname.blank?
29 yield user if block_given?
29 yield user if block_given?
30 user.save!
30 user.save!
31 user
31 user
32 end
32 end
33
33
34 def Group.generate!(attributes={})
34 def Group.generate!(attributes={})
35 @generated_group_name ||= 'Group 0'
35 @generated_group_name ||= 'Group 0'
36 @generated_group_name.succ!
36 @generated_group_name.succ!
37 group = Group.new(attributes)
37 group = Group.new(attributes)
38 group.lastname = @generated_group_name if group.lastname.blank?
38 group.lastname = @generated_group_name if group.lastname.blank?
39 yield group if block_given?
39 yield group if block_given?
40 group.save!
40 group.save!
41 group
41 group
42 end
42 end
43
43
44 def Project.generate!(attributes={})
44 def Project.generate!(attributes={})
45 @generated_project_identifier ||= 'project-0000'
45 @generated_project_identifier ||= 'project-0000'
46 @generated_project_identifier.succ!
46 @generated_project_identifier.succ!
47 project = Project.new(attributes)
47 project = Project.new(attributes)
48 project.name = @generated_project_identifier if project.name.blank?
48 project.name = @generated_project_identifier if project.name.blank?
49 project.identifier = @generated_project_identifier if project.identifier.blank?
49 project.identifier = @generated_project_identifier if project.identifier.blank?
50 yield project if block_given?
50 yield project if block_given?
51 project.save!
51 project.save!
52 project
52 project
53 end
53 end
54
54
55 def Tracker.generate!(attributes={})
55 def Tracker.generate!(attributes={})
56 @generated_tracker_name ||= 'Tracker 0'
56 @generated_tracker_name ||= 'Tracker 0'
57 @generated_tracker_name.succ!
57 @generated_tracker_name.succ!
58 tracker = Tracker.new(attributes)
58 tracker = Tracker.new(attributes)
59 tracker.name = @generated_tracker_name if tracker.name.blank?
59 tracker.name = @generated_tracker_name if tracker.name.blank?
60 yield tracker if block_given?
60 yield tracker if block_given?
61 tracker.save!
61 tracker.save!
62 tracker
62 tracker
63 end
63 end
64
64
65 def Role.generate!(attributes={})
65 def Role.generate!(attributes={})
66 @generated_role_name ||= 'Role 0'
66 @generated_role_name ||= 'Role 0'
67 @generated_role_name.succ!
67 @generated_role_name.succ!
68 role = Role.new(attributes)
68 role = Role.new(attributes)
69 role.name = @generated_role_name if role.name.blank?
69 role.name = @generated_role_name if role.name.blank?
70 yield role if block_given?
70 yield role if block_given?
71 role.save!
71 role.save!
72 role
72 role
73 end
73 end
74
74
75 def Issue.generate!(attributes={})
75 def Issue.generate!(attributes={})
76 issue = Issue.new(attributes)
76 issue = Issue.new(attributes)
77 issue.subject = 'Generated' if issue.subject.blank?
77 issue.subject = 'Generated' if issue.subject.blank?
78 issue.author ||= User.find(2)
78 issue.author ||= User.find(2)
79 yield issue if block_given?
79 yield issue if block_given?
80 issue.save!
80 issue.save!
81 issue
81 issue
82 end
82 end
83
83
84 def Version.generate!(attributes={})
84 def Version.generate!(attributes={})
85 @generated_version_name ||= 'Version 0'
85 @generated_version_name ||= 'Version 0'
86 @generated_version_name.succ!
86 @generated_version_name.succ!
87 version = Version.new(attributes)
87 version = Version.new(attributes)
88 version.name = @generated_version_name if version.name.blank?
88 version.name = @generated_version_name if version.name.blank?
89 yield version if block_given?
89 yield version if block_given?
90 version.save!
90 version.save!
91 version
91 version
92 end
92 end
93
93
94 def AuthSource.generate!(attributes={})
94 def AuthSource.generate!(attributes={})
95 @generated_auth_source_name ||= 'Auth 0'
95 @generated_auth_source_name ||= 'Auth 0'
96 @generated_auth_source_name.succ!
96 @generated_auth_source_name.succ!
97 source = AuthSource.new(attributes)
97 source = AuthSource.new(attributes)
98 source.name = @generated_auth_source_name if source.name.blank?
98 source.name = @generated_auth_source_name if source.name.blank?
99 yield source if block_given?
99 yield source if block_given?
100 source.save!
100 source.save!
101 source
101 source
102 end
102 end
103
103
104 # Generate the default Query
104 # Generate the default Query
105 def Query.generate_default!(attributes={})
105 def Query.generate_default!(attributes={})
106 query = Query.new(attributes)
106 query = Query.new(attributes)
107 query.name = '_' if query.name.blank?
107 query.name = '_' if query.name.blank?
108 query.save!
108 query.save!
109 query
109 query
110 end
110 end
111
111
112 # Generate an issue for a project, using it's trackers
112 # Generate an issue for a project, using it's trackers
113 def Issue.generate_for_project!(project, attributes={})
113 def Issue.generate_for_project!(project, attributes={})
114 issue = Issue.new(attributes) do |issue|
114 issue = Issue.new(attributes) do |issue|
115 issue.project = project
115 issue.project = project
116 issue.tracker = project.trackers.first unless project.trackers.empty?
116 issue.tracker = project.trackers.first unless project.trackers.empty?
117 issue.subject = 'Generated' if issue.subject.blank?
117 issue.subject = 'Generated' if issue.subject.blank?
118 issue.author ||= User.find(2)
118 issue.author ||= User.find(2)
119 yield issue if block_given?
119 yield issue if block_given?
120 end
120 end
121 issue.save!
121 issue.save!
122 issue
122 issue
123 end
123 end
124 end
124 end
@@ -1,465 +1,465
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 Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
21 require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
22
22
23 require File.expand_path(File.dirname(__FILE__) + '/object_daddy_helpers')
23 require File.expand_path(File.dirname(__FILE__) + '/object_helpers')
24 include ObjectDaddyHelpers
24 include ObjectHelpers
25
25
26 class ActiveSupport::TestCase
26 class ActiveSupport::TestCase
27 # Transactional fixtures accelerate your tests by wrapping each test method
27 # Transactional fixtures accelerate your tests by wrapping each test method
28 # in a transaction that's rolled back on completion. This ensures that the
28 # in a transaction that's rolled back on completion. This ensures that the
29 # test database remains unchanged so your fixtures don't have to be reloaded
29 # test database remains unchanged so your fixtures don't have to be reloaded
30 # between every test method. Fewer database queries means faster tests.
30 # between every test method. Fewer database queries means faster tests.
31 #
31 #
32 # Read Mike Clark's excellent walkthrough at
32 # Read Mike Clark's excellent walkthrough at
33 # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
33 # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
34 #
34 #
35 # Every Active Record database supports transactions except MyISAM tables
35 # Every Active Record database supports transactions except MyISAM tables
36 # in MySQL. Turn off transactional fixtures in this case; however, if you
36 # in MySQL. Turn off transactional fixtures in this case; however, if you
37 # don't care one way or the other, switching from MyISAM to InnoDB tables
37 # don't care one way or the other, switching from MyISAM to InnoDB tables
38 # is recommended.
38 # is recommended.
39 self.use_transactional_fixtures = true
39 self.use_transactional_fixtures = true
40
40
41 # Instantiated fixtures are slow, but give you @david where otherwise you
41 # Instantiated fixtures are slow, but give you @david where otherwise you
42 # would need people(:david). If you don't want to migrate your existing
42 # would need people(:david). If you don't want to migrate your existing
43 # test cases which use the @david style and don't mind the speed hit (each
43 # test cases which use the @david style and don't mind the speed hit (each
44 # instantiated fixtures translates to a database query per test method),
44 # instantiated fixtures translates to a database query per test method),
45 # then set this back to true.
45 # then set this back to true.
46 self.use_instantiated_fixtures = false
46 self.use_instantiated_fixtures = false
47
47
48 # Add more helper methods to be used by all tests here...
48 # Add more helper methods to be used by all tests here...
49
49
50 def log_user(login, password)
50 def log_user(login, password)
51 User.anonymous
51 User.anonymous
52 get "/login"
52 get "/login"
53 assert_equal nil, session[:user_id]
53 assert_equal nil, session[:user_id]
54 assert_response :success
54 assert_response :success
55 assert_template "account/login"
55 assert_template "account/login"
56 post "/login", :username => login, :password => password
56 post "/login", :username => login, :password => password
57 assert_equal login, User.find(session[:user_id]).login
57 assert_equal login, User.find(session[:user_id]).login
58 end
58 end
59
59
60 def uploaded_test_file(name, mime)
60 def uploaded_test_file(name, mime)
61 ActionController::TestUploadedFile.new(
61 ActionController::TestUploadedFile.new(
62 ActiveSupport::TestCase.fixture_path + "/files/#{name}", mime, true)
62 ActiveSupport::TestCase.fixture_path + "/files/#{name}", mime, true)
63 end
63 end
64
64
65 def credentials(user, password=nil)
65 def credentials(user, password=nil)
66 {:authorization => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
66 {:authorization => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
67 end
67 end
68
68
69 # Mock out a file
69 # Mock out a file
70 def self.mock_file
70 def self.mock_file
71 file = 'a_file.png'
71 file = 'a_file.png'
72 file.stubs(:size).returns(32)
72 file.stubs(:size).returns(32)
73 file.stubs(:original_filename).returns('a_file.png')
73 file.stubs(:original_filename).returns('a_file.png')
74 file.stubs(:content_type).returns('image/png')
74 file.stubs(:content_type).returns('image/png')
75 file.stubs(:read).returns(false)
75 file.stubs(:read).returns(false)
76 file
76 file
77 end
77 end
78
78
79 def mock_file
79 def mock_file
80 self.class.mock_file
80 self.class.mock_file
81 end
81 end
82
82
83 def mock_file_with_options(options={})
83 def mock_file_with_options(options={})
84 file = ''
84 file = ''
85 file.stubs(:size).returns(32)
85 file.stubs(:size).returns(32)
86 original_filename = options[:original_filename] || nil
86 original_filename = options[:original_filename] || nil
87 file.stubs(:original_filename).returns(original_filename)
87 file.stubs(:original_filename).returns(original_filename)
88 content_type = options[:content_type] || nil
88 content_type = options[:content_type] || nil
89 file.stubs(:content_type).returns(content_type)
89 file.stubs(:content_type).returns(content_type)
90 file.stubs(:read).returns(false)
90 file.stubs(:read).returns(false)
91 file
91 file
92 end
92 end
93
93
94 # Use a temporary directory for attachment related tests
94 # Use a temporary directory for attachment related tests
95 def set_tmp_attachments_directory
95 def set_tmp_attachments_directory
96 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
96 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
97 unless File.directory?("#{Rails.root}/tmp/test/attachments")
97 unless File.directory?("#{Rails.root}/tmp/test/attachments")
98 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
98 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
99 end
99 end
100 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
100 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
101 end
101 end
102
102
103 def set_fixtures_attachments_directory
103 def set_fixtures_attachments_directory
104 Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
104 Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
105 end
105 end
106
106
107 def with_settings(options, &block)
107 def with_settings(options, &block)
108 saved_settings = options.keys.inject({}) {|h, k| h[k] = Setting[k].is_a?(Symbol) ? Setting[k] : Setting[k].dup; h}
108 saved_settings = options.keys.inject({}) {|h, k| h[k] = Setting[k].is_a?(Symbol) ? Setting[k] : Setting[k].dup; h}
109 options.each {|k, v| Setting[k] = v}
109 options.each {|k, v| Setting[k] = v}
110 yield
110 yield
111 ensure
111 ensure
112 saved_settings.each {|k, v| Setting[k] = v} if saved_settings
112 saved_settings.each {|k, v| Setting[k] = v} if saved_settings
113 end
113 end
114
114
115 def change_user_password(login, new_password)
115 def change_user_password(login, new_password)
116 user = User.first(:conditions => {:login => login})
116 user = User.first(:conditions => {:login => login})
117 user.password, user.password_confirmation = new_password, new_password
117 user.password, user.password_confirmation = new_password, new_password
118 user.save!
118 user.save!
119 end
119 end
120
120
121 def self.ldap_configured?
121 def self.ldap_configured?
122 @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
122 @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
123 return @test_ldap.bind
123 return @test_ldap.bind
124 rescue Exception => e
124 rescue Exception => e
125 # LDAP is not listening
125 # LDAP is not listening
126 return nil
126 return nil
127 end
127 end
128
128
129 # Returns the path to the test +vendor+ repository
129 # Returns the path to the test +vendor+ repository
130 def self.repository_path(vendor)
130 def self.repository_path(vendor)
131 Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
131 Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
132 end
132 end
133
133
134 # Returns the url of the subversion test repository
134 # Returns the url of the subversion test repository
135 def self.subversion_repository_url
135 def self.subversion_repository_url
136 path = repository_path('subversion')
136 path = repository_path('subversion')
137 path = '/' + path unless path.starts_with?('/')
137 path = '/' + path unless path.starts_with?('/')
138 "file://#{path}"
138 "file://#{path}"
139 end
139 end
140
140
141 # Returns true if the +vendor+ test repository is configured
141 # Returns true if the +vendor+ test repository is configured
142 def self.repository_configured?(vendor)
142 def self.repository_configured?(vendor)
143 File.directory?(repository_path(vendor))
143 File.directory?(repository_path(vendor))
144 end
144 end
145
145
146 def repository_path_hash(arr)
146 def repository_path_hash(arr)
147 hs = {}
147 hs = {}
148 hs[:path] = arr.join("/")
148 hs[:path] = arr.join("/")
149 hs[:param] = arr
149 hs[:param] = arr
150 hs
150 hs
151 end
151 end
152
152
153 def assert_error_tag(options={})
153 def assert_error_tag(options={})
154 assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options))
154 assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options))
155 end
155 end
156
156
157 def assert_include(expected, s)
157 def assert_include(expected, s)
158 assert s.include?(expected), "\"#{expected}\" not found in \"#{s}\""
158 assert s.include?(expected), "\"#{expected}\" not found in \"#{s}\""
159 end
159 end
160
160
161 def assert_not_include(expected, s)
161 def assert_not_include(expected, s)
162 assert !s.include?(expected), "\"#{expected}\" found in \"#{s}\""
162 assert !s.include?(expected), "\"#{expected}\" found in \"#{s}\""
163 end
163 end
164
164
165 def assert_mail_body_match(expected, mail)
165 def assert_mail_body_match(expected, mail)
166 if expected.is_a?(String)
166 if expected.is_a?(String)
167 assert_include expected, mail_body(mail)
167 assert_include expected, mail_body(mail)
168 else
168 else
169 assert_match expected, mail_body(mail)
169 assert_match expected, mail_body(mail)
170 end
170 end
171 end
171 end
172
172
173 def assert_mail_body_no_match(expected, mail)
173 def assert_mail_body_no_match(expected, mail)
174 if expected.is_a?(String)
174 if expected.is_a?(String)
175 assert_not_include expected, mail_body(mail)
175 assert_not_include expected, mail_body(mail)
176 else
176 else
177 assert_no_match expected, mail_body(mail)
177 assert_no_match expected, mail_body(mail)
178 end
178 end
179 end
179 end
180
180
181 def mail_body(mail)
181 def mail_body(mail)
182 mail.body
182 mail.body
183 end
183 end
184
184
185 # Shoulda macros
185 # Shoulda macros
186 def self.should_render_404
186 def self.should_render_404
187 should_respond_with :not_found
187 should_respond_with :not_found
188 should_render_template 'common/error'
188 should_render_template 'common/error'
189 end
189 end
190
190
191 def self.should_have_before_filter(expected_method, options = {})
191 def self.should_have_before_filter(expected_method, options = {})
192 should_have_filter('before', expected_method, options)
192 should_have_filter('before', expected_method, options)
193 end
193 end
194
194
195 def self.should_have_after_filter(expected_method, options = {})
195 def self.should_have_after_filter(expected_method, options = {})
196 should_have_filter('after', expected_method, options)
196 should_have_filter('after', expected_method, options)
197 end
197 end
198
198
199 def self.should_have_filter(filter_type, expected_method, options)
199 def self.should_have_filter(filter_type, expected_method, options)
200 description = "have #{filter_type}_filter :#{expected_method}"
200 description = "have #{filter_type}_filter :#{expected_method}"
201 description << " with #{options.inspect}" unless options.empty?
201 description << " with #{options.inspect}" unless options.empty?
202
202
203 should description do
203 should description do
204 klass = "action_controller/filters/#{filter_type}_filter".classify.constantize
204 klass = "action_controller/filters/#{filter_type}_filter".classify.constantize
205 expected = klass.new(:filter, expected_method.to_sym, options)
205 expected = klass.new(:filter, expected_method.to_sym, options)
206 assert_equal 1, @controller.class.filter_chain.select { |filter|
206 assert_equal 1, @controller.class.filter_chain.select { |filter|
207 filter.method == expected.method && filter.kind == expected.kind &&
207 filter.method == expected.method && filter.kind == expected.kind &&
208 filter.options == expected.options && filter.class == expected.class
208 filter.options == expected.options && filter.class == expected.class
209 }.size
209 }.size
210 end
210 end
211 end
211 end
212
212
213 # Test that a request allows the three types of API authentication
213 # Test that a request allows the three types of API authentication
214 #
214 #
215 # * HTTP Basic with username and password
215 # * HTTP Basic with username and password
216 # * HTTP Basic with an api key for the username
216 # * HTTP Basic with an api key for the username
217 # * Key based with the key=X parameter
217 # * Key based with the key=X parameter
218 #
218 #
219 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
219 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
220 # @param [String] url the request url
220 # @param [String] url the request url
221 # @param [optional, Hash] parameters additional request parameters
221 # @param [optional, Hash] parameters additional request parameters
222 # @param [optional, Hash] options additional options
222 # @param [optional, Hash] options additional options
223 # @option options [Symbol] :success_code Successful response code (:success)
223 # @option options [Symbol] :success_code Successful response code (:success)
224 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
224 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
225 def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
225 def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
226 should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options)
226 should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options)
227 should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
227 should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
228 should_allow_key_based_auth(http_method, url, parameters, options)
228 should_allow_key_based_auth(http_method, url, parameters, options)
229 end
229 end
230
230
231 # Test that a request allows the username and password for HTTP BASIC
231 # Test that a request allows the username and password for HTTP BASIC
232 #
232 #
233 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
233 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
234 # @param [String] url the request url
234 # @param [String] url the request url
235 # @param [optional, Hash] parameters additional request parameters
235 # @param [optional, Hash] parameters additional request parameters
236 # @param [optional, Hash] options additional options
236 # @param [optional, Hash] options additional options
237 # @option options [Symbol] :success_code Successful response code (:success)
237 # @option options [Symbol] :success_code Successful response code (:success)
238 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
238 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
239 def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
239 def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
240 success_code = options[:success_code] || :success
240 success_code = options[:success_code] || :success
241 failure_code = options[:failure_code] || :unauthorized
241 failure_code = options[:failure_code] || :unauthorized
242
242
243 context "should allow http basic auth using a username and password for #{http_method} #{url}" do
243 context "should allow http basic auth using a username and password for #{http_method} #{url}" do
244 context "with a valid HTTP authentication" do
244 context "with a valid HTTP authentication" do
245 setup do
245 setup do
246 @user = User.generate! do |user|
246 @user = User.generate! do |user|
247 user.admin = true
247 user.admin = true
248 user.password = 'my_password'
248 user.password = 'my_password'
249 end
249 end
250 send(http_method, url, parameters, credentials(@user.login, 'my_password'))
250 send(http_method, url, parameters, credentials(@user.login, 'my_password'))
251 end
251 end
252
252
253 should_respond_with success_code
253 should_respond_with success_code
254 should_respond_with_content_type_based_on_url(url)
254 should_respond_with_content_type_based_on_url(url)
255 should "login as the user" do
255 should "login as the user" do
256 assert_equal @user, User.current
256 assert_equal @user, User.current
257 end
257 end
258 end
258 end
259
259
260 context "with an invalid HTTP authentication" do
260 context "with an invalid HTTP authentication" do
261 setup do
261 setup do
262 @user = User.generate!
262 @user = User.generate!
263 send(http_method, url, parameters, credentials(@user.login, 'wrong_password'))
263 send(http_method, url, parameters, credentials(@user.login, 'wrong_password'))
264 end
264 end
265
265
266 should_respond_with failure_code
266 should_respond_with failure_code
267 should_respond_with_content_type_based_on_url(url)
267 should_respond_with_content_type_based_on_url(url)
268 should "not login as the user" do
268 should "not login as the user" do
269 assert_equal User.anonymous, User.current
269 assert_equal User.anonymous, User.current
270 end
270 end
271 end
271 end
272
272
273 context "without credentials" do
273 context "without credentials" do
274 setup do
274 setup do
275 send(http_method, url, parameters)
275 send(http_method, url, parameters)
276 end
276 end
277
277
278 should_respond_with failure_code
278 should_respond_with failure_code
279 should_respond_with_content_type_based_on_url(url)
279 should_respond_with_content_type_based_on_url(url)
280 should "include_www_authenticate_header" do
280 should "include_www_authenticate_header" do
281 assert @controller.response.headers.has_key?('WWW-Authenticate')
281 assert @controller.response.headers.has_key?('WWW-Authenticate')
282 end
282 end
283 end
283 end
284 end
284 end
285
285
286 end
286 end
287
287
288 # Test that a request allows the API key with HTTP BASIC
288 # Test that a request allows the API key with HTTP BASIC
289 #
289 #
290 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
290 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
291 # @param [String] url the request url
291 # @param [String] url the request url
292 # @param [optional, Hash] parameters additional request parameters
292 # @param [optional, Hash] parameters additional request parameters
293 # @param [optional, Hash] options additional options
293 # @param [optional, Hash] options additional options
294 # @option options [Symbol] :success_code Successful response code (:success)
294 # @option options [Symbol] :success_code Successful response code (:success)
295 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
295 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
296 def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
296 def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
297 success_code = options[:success_code] || :success
297 success_code = options[:success_code] || :success
298 failure_code = options[:failure_code] || :unauthorized
298 failure_code = options[:failure_code] || :unauthorized
299
299
300 context "should allow http basic auth with a key for #{http_method} #{url}" do
300 context "should allow http basic auth with a key for #{http_method} #{url}" do
301 context "with a valid HTTP authentication using the API token" do
301 context "with a valid HTTP authentication using the API token" do
302 setup do
302 setup do
303 @user = User.generate! do |user|
303 @user = User.generate! do |user|
304 user.admin = true
304 user.admin = true
305 end
305 end
306 @token = Token.create!(:user => @user, :action => 'api')
306 @token = Token.create!(:user => @user, :action => 'api')
307 send(http_method, url, parameters, credentials(@token.value, 'X'))
307 send(http_method, url, parameters, credentials(@token.value, 'X'))
308 end
308 end
309
309
310 should_respond_with success_code
310 should_respond_with success_code
311 should_respond_with_content_type_based_on_url(url)
311 should_respond_with_content_type_based_on_url(url)
312 should_be_a_valid_response_string_based_on_url(url)
312 should_be_a_valid_response_string_based_on_url(url)
313 should "login as the user" do
313 should "login as the user" do
314 assert_equal @user, User.current
314 assert_equal @user, User.current
315 end
315 end
316 end
316 end
317
317
318 context "with an invalid HTTP authentication" do
318 context "with an invalid HTTP authentication" do
319 setup do
319 setup do
320 @user = User.generate!
320 @user = User.generate!
321 @token = Token.create!(:user => @user, :action => 'feeds')
321 @token = Token.create!(:user => @user, :action => 'feeds')
322 send(http_method, url, parameters, credentials(@token.value, 'X'))
322 send(http_method, url, parameters, credentials(@token.value, 'X'))
323 end
323 end
324
324
325 should_respond_with failure_code
325 should_respond_with failure_code
326 should_respond_with_content_type_based_on_url(url)
326 should_respond_with_content_type_based_on_url(url)
327 should "not login as the user" do
327 should "not login as the user" do
328 assert_equal User.anonymous, User.current
328 assert_equal User.anonymous, User.current
329 end
329 end
330 end
330 end
331 end
331 end
332 end
332 end
333
333
334 # Test that a request allows full key authentication
334 # Test that a request allows full key authentication
335 #
335 #
336 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
336 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
337 # @param [String] url the request url, without the key=ZXY parameter
337 # @param [String] url the request url, without the key=ZXY parameter
338 # @param [optional, Hash] parameters additional request parameters
338 # @param [optional, Hash] parameters additional request parameters
339 # @param [optional, Hash] options additional options
339 # @param [optional, Hash] options additional options
340 # @option options [Symbol] :success_code Successful response code (:success)
340 # @option options [Symbol] :success_code Successful response code (:success)
341 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
341 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
342 def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
342 def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
343 success_code = options[:success_code] || :success
343 success_code = options[:success_code] || :success
344 failure_code = options[:failure_code] || :unauthorized
344 failure_code = options[:failure_code] || :unauthorized
345
345
346 context "should allow key based auth using key=X for #{http_method} #{url}" do
346 context "should allow key based auth using key=X for #{http_method} #{url}" do
347 context "with a valid api token" do
347 context "with a valid api token" do
348 setup do
348 setup do
349 @user = User.generate! do |user|
349 @user = User.generate! do |user|
350 user.admin = true
350 user.admin = true
351 end
351 end
352 @token = Token.create!(:user => @user, :action => 'api')
352 @token = Token.create!(:user => @user, :action => 'api')
353 # Simple url parse to add on ?key= or &key=
353 # Simple url parse to add on ?key= or &key=
354 request_url = if url.match(/\?/)
354 request_url = if url.match(/\?/)
355 url + "&key=#{@token.value}"
355 url + "&key=#{@token.value}"
356 else
356 else
357 url + "?key=#{@token.value}"
357 url + "?key=#{@token.value}"
358 end
358 end
359 send(http_method, request_url, parameters)
359 send(http_method, request_url, parameters)
360 end
360 end
361
361
362 should_respond_with success_code
362 should_respond_with success_code
363 should_respond_with_content_type_based_on_url(url)
363 should_respond_with_content_type_based_on_url(url)
364 should_be_a_valid_response_string_based_on_url(url)
364 should_be_a_valid_response_string_based_on_url(url)
365 should "login as the user" do
365 should "login as the user" do
366 assert_equal @user, User.current
366 assert_equal @user, User.current
367 end
367 end
368 end
368 end
369
369
370 context "with an invalid api token" do
370 context "with an invalid api token" do
371 setup do
371 setup do
372 @user = User.generate! do |user|
372 @user = User.generate! do |user|
373 user.admin = true
373 user.admin = true
374 end
374 end
375 @token = Token.create!(:user => @user, :action => 'feeds')
375 @token = Token.create!(:user => @user, :action => 'feeds')
376 # Simple url parse to add on ?key= or &key=
376 # Simple url parse to add on ?key= or &key=
377 request_url = if url.match(/\?/)
377 request_url = if url.match(/\?/)
378 url + "&key=#{@token.value}"
378 url + "&key=#{@token.value}"
379 else
379 else
380 url + "?key=#{@token.value}"
380 url + "?key=#{@token.value}"
381 end
381 end
382 send(http_method, request_url, parameters)
382 send(http_method, request_url, parameters)
383 end
383 end
384
384
385 should_respond_with failure_code
385 should_respond_with failure_code
386 should_respond_with_content_type_based_on_url(url)
386 should_respond_with_content_type_based_on_url(url)
387 should "not login as the user" do
387 should "not login as the user" do
388 assert_equal User.anonymous, User.current
388 assert_equal User.anonymous, User.current
389 end
389 end
390 end
390 end
391 end
391 end
392
392
393 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
393 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
394 setup do
394 setup do
395 @user = User.generate! do |user|
395 @user = User.generate! do |user|
396 user.admin = true
396 user.admin = true
397 end
397 end
398 @token = Token.create!(:user => @user, :action => 'api')
398 @token = Token.create!(:user => @user, :action => 'api')
399 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
399 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
400 end
400 end
401
401
402 should_respond_with success_code
402 should_respond_with success_code
403 should_respond_with_content_type_based_on_url(url)
403 should_respond_with_content_type_based_on_url(url)
404 should_be_a_valid_response_string_based_on_url(url)
404 should_be_a_valid_response_string_based_on_url(url)
405 should "login as the user" do
405 should "login as the user" do
406 assert_equal @user, User.current
406 assert_equal @user, User.current
407 end
407 end
408 end
408 end
409 end
409 end
410
410
411 # Uses should_respond_with_content_type based on what's in the url:
411 # Uses should_respond_with_content_type based on what's in the url:
412 #
412 #
413 # '/project/issues.xml' => should_respond_with_content_type :xml
413 # '/project/issues.xml' => should_respond_with_content_type :xml
414 # '/project/issues.json' => should_respond_with_content_type :json
414 # '/project/issues.json' => should_respond_with_content_type :json
415 #
415 #
416 # @param [String] url Request
416 # @param [String] url Request
417 def self.should_respond_with_content_type_based_on_url(url)
417 def self.should_respond_with_content_type_based_on_url(url)
418 case
418 case
419 when url.match(/xml/i)
419 when url.match(/xml/i)
420 should_respond_with_content_type :xml
420 should_respond_with_content_type :xml
421 when url.match(/json/i)
421 when url.match(/json/i)
422 should_respond_with_content_type :json
422 should_respond_with_content_type :json
423 else
423 else
424 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
424 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
425 end
425 end
426
426
427 end
427 end
428
428
429 # Uses the url to assert which format the response should be in
429 # Uses the url to assert which format the response should be in
430 #
430 #
431 # '/project/issues.xml' => should_be_a_valid_xml_string
431 # '/project/issues.xml' => should_be_a_valid_xml_string
432 # '/project/issues.json' => should_be_a_valid_json_string
432 # '/project/issues.json' => should_be_a_valid_json_string
433 #
433 #
434 # @param [String] url Request
434 # @param [String] url Request
435 def self.should_be_a_valid_response_string_based_on_url(url)
435 def self.should_be_a_valid_response_string_based_on_url(url)
436 case
436 case
437 when url.match(/xml/i)
437 when url.match(/xml/i)
438 should_be_a_valid_xml_string
438 should_be_a_valid_xml_string
439 when url.match(/json/i)
439 when url.match(/json/i)
440 should_be_a_valid_json_string
440 should_be_a_valid_json_string
441 else
441 else
442 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
442 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
443 end
443 end
444
444
445 end
445 end
446
446
447 # Checks that the response is a valid JSON string
447 # Checks that the response is a valid JSON string
448 def self.should_be_a_valid_json_string
448 def self.should_be_a_valid_json_string
449 should "be a valid JSON string (or empty)" do
449 should "be a valid JSON string (or empty)" do
450 assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
450 assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
451 end
451 end
452 end
452 end
453
453
454 # Checks that the response is a valid XML string
454 # Checks that the response is a valid XML string
455 def self.should_be_a_valid_xml_string
455 def self.should_be_a_valid_xml_string
456 should "be a valid XML string" do
456 should "be a valid XML string" do
457 assert REXML::Document.new(response.body)
457 assert REXML::Document.new(response.body)
458 end
458 end
459 end
459 end
460
460
461 end
461 end
462
462
463 # Simple module to "namespace" all of the API tests
463 # Simple module to "namespace" all of the API tests
464 module ApiTest
464 module ApiTest
465 end
465 end
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now