##// END OF EJS Templates
Removed some test contexts....
Jean-Philippe Lang -
r13264:4989c9f6a845
parent child
Show More
@@ -1,54 +1,43
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../../test_helper', __FILE__)
19 19
20 20 class Redmine::ApiTest::HttpBasicLoginTest < Redmine::ApiTest::Base
21 21 fixtures :projects, :trackers, :issue_statuses, :issues,
22 22 :enumerations, :users, :issue_categories,
23 23 :projects_trackers,
24 24 :roles,
25 25 :member_roles,
26 26 :members,
27 27 :enabled_modules
28 28
29 29 def setup
30 30 Setting.rest_api_enabled = '1'
31 31 Setting.login_required = '1'
32 project = Project.find('onlinestore')
33 EnabledModule.create(:project => project, :name => 'news')
32 34 end
33 35
34 36 def teardown
35 37 Setting.rest_api_enabled = '0'
36 38 Setting.login_required = '0'
37 39 end
38 40
39 # Using the NewsController because it's a simple API.
40 context "get /news" do
41 setup do
42 project = Project.find('onlinestore')
43 EnabledModule.create(:project => project, :name => 'news')
44 end
45
46 context "in :xml format" do
47 41 should_allow_http_basic_auth_with_username_and_password(:get, "/projects/onlinestore/news.xml")
48 end
49
50 context "in :json format" do
51 42 should_allow_http_basic_auth_with_username_and_password(:get, "/projects/onlinestore/news.json")
52 43 end
53 end
54 end
@@ -1,50 +1,41
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../../test_helper', __FILE__)
19 19
20 20 class Redmine::ApiTest::HttpBasicLoginWithApiTokenTest < Redmine::ApiTest::Base
21 21 fixtures :projects, :trackers, :issue_statuses, :issues,
22 22 :enumerations, :users, :issue_categories,
23 23 :projects_trackers,
24 24 :roles,
25 25 :member_roles,
26 26 :members,
27 27 :enabled_modules
28 28
29 29 def setup
30 30 Setting.rest_api_enabled = '1'
31 31 Setting.login_required = '1'
32 32 end
33 33
34 34 def teardown
35 35 Setting.rest_api_enabled = '0'
36 36 Setting.login_required = '0'
37 37 end
38 38
39 # Using the NewsController because it's a simple API.
40 context "get /news" do
41
42 context "in :xml format" do
43 39 should_allow_http_basic_auth_with_key(:get, "/news.xml")
44 end
45
46 context "in :json format" do
47 40 should_allow_http_basic_auth_with_key(:get, "/news.json")
48 41 end
49 end
50 end
@@ -1,799 +1,632
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../../test_helper', __FILE__)
19 19
20 20 class Redmine::ApiTest::IssuesTest < Redmine::ApiTest::Base
21 21 fixtures :projects,
22 22 :users,
23 23 :roles,
24 24 :members,
25 25 :member_roles,
26 26 :issues,
27 27 :issue_statuses,
28 28 :issue_relations,
29 29 :versions,
30 30 :trackers,
31 31 :projects_trackers,
32 32 :issue_categories,
33 33 :enabled_modules,
34 34 :enumerations,
35 35 :attachments,
36 36 :workflows,
37 37 :custom_fields,
38 38 :custom_values,
39 39 :custom_fields_projects,
40 40 :custom_fields_trackers,
41 41 :time_entries,
42 42 :journals,
43 43 :journal_details,
44 44 :queries,
45 45 :attachments
46 46
47 47 def setup
48 48 Setting.rest_api_enabled = '1'
49 49 end
50 50
51 context "/issues" do
52 51 # Use a private project to make sure auth is really working and not just
53 52 # only showing public issues.
54 53 should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
54 should_allow_api_authentication(:get, "/projects/private-child/issues.json")
55 55
56 should "contain metadata" do
57 get '/issues.xml'
56 should_allow_api_authentication(:get, "/issues/6.xml")
57 should_allow_api_authentication(:get, "/issues/6.json")
58 58
59 assert_select 'issues[type=array][total_count=?][limit="25"][offset="0"]', assigns(:issue_count).to_s
60 end
59 should_allow_api_authentication(
60 :post,
61 '/issues.xml',
62 {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
63 {:success_code => :created}
64 )
65 should_allow_api_authentication(:post,
66 '/issues.json',
67 {:issue => {:project_id => 1, :subject => 'API test',
68 :tracker_id => 2, :status_id => 3}},
69 {:success_code => :created})
61 70
62 context "with offset and limit" do
63 should "use the params" do
64 get '/issues.xml?offset=2&limit=3'
71 should_allow_api_authentication(:put,
72 '/issues/6.xml',
73 {:issue => {:subject => 'API update', :notes => 'A new note'}},
74 {:success_code => :ok})
75 should_allow_api_authentication(:put,
76 '/issues/6.json',
77 {:issue => {:subject => 'API update', :notes => 'A new note'}},
78 {:success_code => :ok})
65 79
66 assert_equal 3, assigns(:limit)
67 assert_equal 2, assigns(:offset)
68 assert_select 'issues issue', 3
69 end
80 should_allow_api_authentication(:delete,
81 '/issues/6.xml',
82 {},
83 {:success_code => :ok})
84 should_allow_api_authentication(:delete,
85 '/issues/6.json',
86 {},
87 {:success_code => :ok})
88
89 test "GET /issues.xml should contain metadata" do
90 get '/issues.xml'
91 assert_select 'issues[type=array][total_count=?][limit="25"][offset="0"]',
92 assigns(:issue_count).to_s
70 93 end
71 94
72 context "with nometa param" do
73 should "not contain metadata" do
95 test "GET /issues.xml with nometa param should not contain metadata" do
74 96 get '/issues.xml?nometa=1'
75
76 97 assert_select 'issues[type=array]:not([total_count]):not([limit]):not([offset])'
77 98 end
78 end
79 99
80 context "with nometa header" do
81 should "not contain metadata" do
100 test "GET /issues.xml with nometa header should not contain metadata" do
82 101 get '/issues.xml', {}, {'X-Redmine-Nometa' => '1'}
83
84 102 assert_select 'issues[type=array]:not([total_count]):not([limit]):not([offset])'
85 103 end
104
105 test "GET /issues.xml with offset and limit" do
106 get '/issues.xml?offset=2&limit=3'
107
108 assert_equal 3, assigns(:limit)
109 assert_equal 2, assigns(:offset)
110 assert_select 'issues issue', 3
86 111 end
87 112
88 context "with relations" do
89 should "display relations" do
113 test "GET /issues.xml with relations" do
90 114 get '/issues.xml?include=relations'
91 115
92 116 assert_response :success
93 117 assert_equal 'application/xml', @response.content_type
94 118
95 119 assert_select 'issue id:content(3)' do
96 120 assert_select '~ relations relation', 1
97 121 assert_select '~ relations relation[id="2"][issue_id="2"][issue_to_id="3"][relation_type=relates]'
98 122 end
99 123
100 124 assert_select 'issue id:content(1)' do
101 125 assert_select '~ relations'
102 126 assert_select '~ relations relation', 0
103 127 end
104 128 end
105 end
106 129
107 context "with invalid query params" do
108 should "return errors" do
130 test "GET /issues.xml with invalid query params" do
109 131 get '/issues.xml', {:f => ['start_date'], :op => {:start_date => '='}}
110 132
111 133 assert_response :unprocessable_entity
112 134 assert_equal 'application/xml', @response.content_type
113 135 assert_select 'errors error', :text => "Start date can't be blank"
114 136 end
115 end
116 137
117 context "with custom field filter" do
118 should "show only issues with the custom field value" do
138 test "GET /issues.xml with custom field filter" do
119 139 get '/issues.xml',
120 {:set_filter => 1, :f => ['cf_1'], :op => {:cf_1 => '='},
121 :v => {:cf_1 => ['MySQL']}}
140 {:set_filter => 1, :f => ['cf_1'], :op => {:cf_1 => '='}, :v => {:cf_1 => ['MySQL']}}
141
122 142 expected_ids = Issue.visible.
123 143 joins(:custom_values).
124 144 where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
145 assert expected_ids.any?
146
125 147 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
126 148 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
127 149 end
128 150 end
129 end
130 151
131 context "with custom field filter (shorthand method)" do
132 should "show only issues with the custom field value" do
152 test "GET /issues.xml with custom field filter (shorthand method)" do
133 153 get '/issues.xml', { :cf_1 => 'MySQL' }
134 154
135 155 expected_ids = Issue.visible.
136 156 joins(:custom_values).
137 157 where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
158 assert expected_ids.any?
138 159
139 160 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
140 161 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
141 162 end
142 163 end
143 end
144 end
145 164
146 165 def test_index_should_include_issue_attributes
147 166 get '/issues.xml'
148 167 assert_select 'issues>issue>is_private', :text => 'false'
149 168 end
150 169
151 170 def test_index_should_allow_timestamp_filtering
152 171 Issue.delete_all
153 172 Issue.generate!(:subject => '1').update_column(:updated_on, Time.parse("2014-01-02T10:25:00Z"))
154 173 Issue.generate!(:subject => '2').update_column(:updated_on, Time.parse("2014-01-02T12:13:00Z"))
155 174
156 175 get '/issues.xml',
157 176 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '<='},
158 177 :v => {:updated_on => ['2014-01-02T12:00:00Z']}}
159 178 assert_select 'issues>issue', :count => 1
160 179 assert_select 'issues>issue>subject', :text => '1'
161 180
162 181 get '/issues.xml',
163 182 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '>='},
164 183 :v => {:updated_on => ['2014-01-02T12:00:00Z']}}
165 184 assert_select 'issues>issue', :count => 1
166 185 assert_select 'issues>issue>subject', :text => '2'
167 186
168 187 get '/issues.xml',
169 188 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '>='},
170 189 :v => {:updated_on => ['2014-01-02T08:00:00Z']}}
171 190 assert_select 'issues>issue', :count => 2
172 191 end
173 192
174 context "/index.json" do
175 should_allow_api_authentication(:get, "/projects/private-child/issues.json")
176 end
177
178 context "/index.xml with filter" do
179 should "show only issues with the status_id" do
193 test "GET /issues.xml with filter" do
180 194 get '/issues.xml?status_id=5'
181 195
182 196 expected_ids = Issue.visible.where(:status_id => 5).map(&:id)
197 assert expected_ids.any?
183 198
184 199 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
185 200 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
186 201 end
187 202 end
188 end
189 203
190 context "/index.json with filter" do
191 should "show only issues with the status_id" do
204 test "GET /issues.json with filter" do
192 205 get '/issues.json?status_id=5'
193 206
194 207 json = ActiveSupport::JSON.decode(response.body)
195 208 status_ids_used = json['issues'].collect {|j| j['status']['id'] }
196 209 assert_equal 3, status_ids_used.length
197 210 assert status_ids_used.all? {|id| id == 5 }
198 211 end
199 212
200 end
201
202 # Issue 6 is on a private project
203 context "/issues/6.xml" do
204 should_allow_api_authentication(:get, "/issues/6.xml")
205 end
206
207 context "/issues/6.json" do
208 should_allow_api_authentication(:get, "/issues/6.json")
209 end
210
211 context "GET /issues/:id" do
212 context "with journals" do
213 context ".xml" do
214 should "display journals" do
213 test "GET /issues/:id.xml with journals" do
215 214 get '/issues/1.xml?include=journals'
216 215
217 216 assert_select 'issue journals[type=array]' do
218 217 assert_select 'journal[id="1"]' do
219 218 assert_select 'details[type=array]' do
220 219 assert_select 'detail[name=status_id]' do
221 220 assert_select 'old_value', :text => '1'
222 221 assert_select 'new_value', :text => '2'
223 222 end
224 223 end
225 224 end
226 225 end
227 226 end
228 end
229 end
230 227
231 context "with custom fields" do
232 context ".xml" do
233 should "display custom fields" do
228 test "GET /issues/:id.xml with custom fields" do
234 229 get '/issues/3.xml'
235 230
236 231 assert_select 'issue custom_fields[type=array]' do
237 232 assert_select 'custom_field[id="1"]' do
238 233 assert_select 'value', :text => 'MySQL'
239 234 end
240 235 end
241
242 236 assert_nothing_raised do
243 237 Hash.from_xml(response.body).to_xml
244 238 end
245 239 end
246 end
247 end
248 240
249 context "with multi custom fields" do
250 setup do
241 test "GET /issues/:id.xml with multi custom fields" do
251 242 field = CustomField.find(1)
252 243 field.update_attribute :multiple, true
253 244 issue = Issue.find(3)
254 245 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
255 246 issue.save!
256 end
257 247
258 context ".xml" do
259 should "display custom fields" do
260 248 get '/issues/3.xml'
261 249 assert_response :success
262 250
263 251 assert_select 'issue custom_fields[type=array]' do
264 252 assert_select 'custom_field[id="1"]' do
265 253 assert_select 'value[type=array] value', 2
266 254 end
267 255 end
268
269 256 xml = Hash.from_xml(response.body)
270 257 custom_fields = xml['issue']['custom_fields']
271 258 assert_kind_of Array, custom_fields
272 259 field = custom_fields.detect {|f| f['id'] == '1'}
273 260 assert_kind_of Hash, field
274 261 assert_equal ['MySQL', 'Oracle'], field['value'].sort
275 262 end
276 end
277 263
278 context ".json" do
279 should "display custom fields" do
264 test "GET /issues/:id.json with multi custom fields" do
265 field = CustomField.find(1)
266 field.update_attribute :multiple, true
267 issue = Issue.find(3)
268 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
269 issue.save!
270
280 271 get '/issues/3.json'
281 272 assert_response :success
273
282 274 json = ActiveSupport::JSON.decode(response.body)
283 275 custom_fields = json['issue']['custom_fields']
284 276 assert_kind_of Array, custom_fields
285 277 field = custom_fields.detect {|f| f['id'] == 1}
286 278 assert_kind_of Hash, field
287 279 assert_equal ['MySQL', 'Oracle'], field['value'].sort
288 280 end
289 end
290 end
291 281
292 context "with empty value for multi custom field" do
293 setup do
282 test "GET /issues/:id.xml with empty value for multi custom field" do
294 283 field = CustomField.find(1)
295 284 field.update_attribute :multiple, true
296 285 issue = Issue.find(3)
297 286 issue.custom_field_values = {1 => ['']}
298 287 issue.save!
299 end
300 288
301 context ".xml" do
302 should "display custom fields" do
303 289 get '/issues/3.xml'
304 290
305 291 assert_select 'issue custom_fields[type=array]' do
306 292 assert_select 'custom_field[id="1"]' do
307 293 assert_select 'value[type=array]:empty'
308 294 end
309 295 end
310
311 296 xml = Hash.from_xml(response.body)
312 297 custom_fields = xml['issue']['custom_fields']
313 298 assert_kind_of Array, custom_fields
314 299 field = custom_fields.detect {|f| f['id'] == '1'}
315 300 assert_kind_of Hash, field
316 301 assert_equal [], field['value']
317 302 end
318 end
319 303
320 context ".json" do
321 should "display custom fields" do
304 test "GET /issues/:id.json with empty value for multi custom field" do
305 field = CustomField.find(1)
306 field.update_attribute :multiple, true
307 issue = Issue.find(3)
308 issue.custom_field_values = {1 => ['']}
309 issue.save!
310
322 311 get '/issues/3.json'
323 312 assert_response :success
324 313 json = ActiveSupport::JSON.decode(response.body)
325 314 custom_fields = json['issue']['custom_fields']
326 315 assert_kind_of Array, custom_fields
327 316 field = custom_fields.detect {|f| f['id'] == 1}
328 317 assert_kind_of Hash, field
329 318 assert_equal [], field['value'].sort
330 319 end
331 end
332 end
333 320
334 context "with attachments" do
335 context ".xml" do
336 should "display attachments" do
321 test "GET /issues/:id.xml with attachments" do
337 322 get '/issues/3.xml?include=attachments'
338 323
339 324 assert_select 'issue attachments[type=array]' do
340 325 assert_select 'attachment', 5
341 326 assert_select 'attachment id:content(4)' do
342 327 assert_select '~ filename', :text => 'source.rb'
343 328 assert_select '~ content_url', :text => 'http://www.example.com/attachments/download/4/source.rb'
344 329 end
345 330 end
346 331 end
347 end
348 end
349 332
350 context "with subtasks" do
351 setup do
352 @c1 = Issue.create!(
353 :status_id => 1, :subject => "child c1",
354 :tracker_id => 1, :project_id => 1, :author_id => 1,
355 :parent_issue_id => 1
356 )
357 @c2 = Issue.create!(
358 :status_id => 1, :subject => "child c2",
359 :tracker_id => 1, :project_id => 1, :author_id => 1,
360 :parent_issue_id => 1
361 )
362 @c3 = Issue.create!(
363 :status_id => 1, :subject => "child c3",
364 :tracker_id => 1, :project_id => 1, :author_id => 1,
365 :parent_issue_id => @c1.id
366 )
367 end
368
369 context ".xml" do
370 should "display children" do
371 get '/issues/1.xml?include=children'
333 test "GET /issues/:id.xml with subtasks" do
334 issue = Issue.generate_with_descendants!(:project_id => 1)
335 get "/issues/#{issue.id}.xml?include=children"
372 336
373 337 assert_select 'issue children[type=array]' do
374 338 assert_select 'issue', 2
375 assert_select 'issue[id=?]', @c1.id.to_s do
376 assert_select 'subject', :text => 'child c1'
377 assert_select 'children' do
378 assert_select 'issue[id=?]', @c3.id.to_s
379 end
380 end
339 assert_select 'issue children', 1
381 340 end
382 341 end
383 342
384 context ".json" do
385 should "display children" do
386 get '/issues/1.json?include=children'
343 test "GET /issues/:id.json with subtasks" do
344 issue = Issue.generate_with_descendants!(:project_id => 1)
345 get "/issues/#{issue.id}.json?include=children"
387 346
388 347 json = ActiveSupport::JSON.decode(response.body)
389 assert_equal([
390 {
391 'id' => @c1.id, 'subject' => 'child c1', 'tracker' => {'id' => 1, 'name' => 'Bug'},
392 'children' => [{'id' => @c3.id, 'subject' => 'child c3',
393 'tracker' => {'id' => 1, 'name' => 'Bug'} }]
394 },
395 { 'id' => @c2.id, 'subject' => 'child c2', 'tracker' => {'id' => 1, 'name' => 'Bug'} }
396 ],
397 json['issue']['children'])
398 end
399 end
400 end
401 end
348 assert_equal 2, json['issue']['children'].size
349 assert_equal 1, json['issue']['children'].select {|child| child.key?('children')}.size
402 350 end
403 351
404 352 def test_show_should_include_issue_attributes
405 353 get '/issues/1.xml'
406 354 assert_select 'issue>is_private', :text => 'false'
407 355 end
408 356
409 357 test "GET /issues/:id.xml?include=watchers should include watchers" do
410 358 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
411 359
412 360 get '/issues/1.xml?include=watchers', {}, credentials('jsmith')
413 361
414 362 assert_response :ok
415 363 assert_equal 'application/xml', response.content_type
416 364 assert_select 'issue' do
417 365 assert_select 'watchers', Issue.find(1).watchers.count
418 366 assert_select 'watchers' do
419 367 assert_select 'user[id=3]'
420 368 end
421 369 end
422 370 end
423 371
424 context "POST /issues.xml" do
425 should_allow_api_authentication(
426 :post,
427 '/issues.xml',
428 {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
429 {:success_code => :created}
430 )
431 should "create an issue with the attributes" do
372 test "POST /issues.xml should create an issue with the attributes" do
432 373 assert_difference('Issue.count') do
433 374 post '/issues.xml',
434 375 {:issue => {:project_id => 1, :subject => 'API test',
435 376 :tracker_id => 2, :status_id => 3}}, credentials('jsmith')
436 377 end
437 378 issue = Issue.order('id DESC').first
438 379 assert_equal 1, issue.project_id
439 380 assert_equal 2, issue.tracker_id
440 381 assert_equal 3, issue.status_id
441 382 assert_equal 'API test', issue.subject
442 383
443 384 assert_response :created
444 385 assert_equal 'application/xml', @response.content_type
445 386 assert_select 'issue > id', :text => issue.id.to_s
446 387 end
447 end
448 388
449 389 test "POST /issues.xml with watcher_user_ids should create issue with watchers" do
450 390 assert_difference('Issue.count') do
451 391 post '/issues.xml',
452 392 {:issue => {:project_id => 1, :subject => 'Watchers',
453 393 :tracker_id => 2, :status_id => 3, :watcher_user_ids => [3, 1]}}, credentials('jsmith')
454 394 assert_response :created
455 395 end
456 396 issue = Issue.order('id desc').first
457 397 assert_equal 2, issue.watchers.size
458 398 assert_equal [1, 3], issue.watcher_user_ids.sort
459 399 end
460 400
461 context "POST /issues.xml with failure" do
462 should "have an errors tag" do
401 test "POST /issues.xml with failure should return errors" do
463 402 assert_no_difference('Issue.count') do
464 403 post '/issues.xml', {:issue => {:project_id => 1}}, credentials('jsmith')
465 404 end
466 405
467 406 assert_select 'errors error', :text => "Subject can't be blank"
468 407 end
469 end
470
471 context "POST /issues.json" do
472 should_allow_api_authentication(:post,
473 '/issues.json',
474 {:issue => {:project_id => 1, :subject => 'API test',
475 :tracker_id => 2, :status_id => 3}},
476 {:success_code => :created})
477 408
478 should "create an issue with the attributes" do
409 test "POST /issues.json should create an issue with the attributes" do
479 410 assert_difference('Issue.count') do
480 411 post '/issues.json',
481 412 {:issue => {:project_id => 1, :subject => 'API test',
482 413 :tracker_id => 2, :status_id => 3}},
483 414 credentials('jsmith')
484 415 end
485 416
486 417 issue = Issue.order('id DESC').first
487 418 assert_equal 1, issue.project_id
488 419 assert_equal 2, issue.tracker_id
489 420 assert_equal 3, issue.status_id
490 421 assert_equal 'API test', issue.subject
491 422 end
492 423
493 end
494
495 context "POST /issues.json with failure" do
496 should "have an errors element" do
424 test "POST /issues.json with failure should return errors" do
497 425 assert_no_difference('Issue.count') do
498 426 post '/issues.json', {:issue => {:project_id => 1}}, credentials('jsmith')
499 427 end
500 428
501 429 json = ActiveSupport::JSON.decode(response.body)
502 430 assert json['errors'].include?("Subject can't be blank")
503 431 end
504 end
505
506 # Issue 6 is on a private project
507 context "PUT /issues/6.xml" do
508 setup do
509 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
510 end
511
512 should_allow_api_authentication(:put,
513 '/issues/6.xml',
514 {:issue => {:subject => 'API update', :notes => 'A new note'}},
515 {:success_code => :ok})
516
517 should "not create a new issue" do
518 assert_no_difference('Issue.count') do
519 put '/issues/6.xml', @parameters, credentials('jsmith')
520 end
521 end
522 432
523 should "create a new journal" do
433 test "PUT /issues/:id.xml" do
524 434 assert_difference('Journal.count') do
525 put '/issues/6.xml', @parameters, credentials('jsmith')
526 end
527 end
528
529 should "add the note to the journal" do
530 put '/issues/6.xml', @parameters, credentials('jsmith')
531
532 journal = Journal.last
533 assert_equal "A new note", journal.notes
435 put '/issues/6.xml',
436 {:issue => {:subject => 'API update', :notes => 'A new note'}},
437 credentials('jsmith')
534 438 end
535 439
536 should "update the issue" do
537 put '/issues/6.xml', @parameters, credentials('jsmith')
538
539 440 issue = Issue.find(6)
540 441 assert_equal "API update", issue.subject
442 journal = Journal.last
443 assert_equal "A new note", journal.notes
541 444 end
542 445
543 end
544
545 context "PUT /issues/3.xml with custom fields" do
546 setup do
547 @parameters = {
548 :issue => {:custom_fields => [{'id' => '1', 'value' => 'PostgreSQL' },
549 {'id' => '2', 'value' => '150'}]}
550 }
551 end
552
553 should "update custom fields" do
554 assert_no_difference('Issue.count') do
555 put '/issues/3.xml', @parameters, credentials('jsmith')
556 end
446 test "PUT /issues/:id.xml with custom fields" do
447 put '/issues/3.xml',
448 {:issue => {:custom_fields => [
449 {'id' => '1', 'value' => 'PostgreSQL' },
450 {'id' => '2', 'value' => '150'}
451 ]}},
452 credentials('jsmith')
557 453
558 454 issue = Issue.find(3)
559 455 assert_equal '150', issue.custom_value_for(2).value
560 456 assert_equal 'PostgreSQL', issue.custom_value_for(1).value
561 457 end
562 end
563 458
564 context "PUT /issues/3.xml with multi custom fields" do
565 setup do
459 test "PUT /issues/:id.xml with multi custom fields" do
566 460 field = CustomField.find(1)
567 461 field.update_attribute :multiple, true
568 @parameters = {
569 :issue => {:custom_fields => [{'id' => '1', 'value' => ['MySQL', 'PostgreSQL'] },
570 {'id' => '2', 'value' => '150'}]}
571 }
572 end
573 462
574 should "update custom fields" do
575 assert_no_difference('Issue.count') do
576 put '/issues/3.xml', @parameters, credentials('jsmith')
577 end
463 put '/issues/3.xml',
464 {:issue => {:custom_fields => [
465 {'id' => '1', 'value' => ['MySQL', 'PostgreSQL'] },
466 {'id' => '2', 'value' => '150'}
467 ]}},
468 credentials('jsmith')
578 469
579 470 issue = Issue.find(3)
580 471 assert_equal '150', issue.custom_value_for(2).value
581 472 assert_equal ['MySQL', 'PostgreSQL'], issue.custom_field_value(1).sort
582 473 end
583 end
584 474
585 context "PUT /issues/3.xml with project change" do
586 setup do
587 @parameters = {:issue => {:project_id => 2, :subject => 'Project changed'}}
588 end
589
590 should "update project" do
591 assert_no_difference('Issue.count') do
592 put '/issues/3.xml', @parameters, credentials('jsmith')
593 end
475 test "PUT /issues/:id.xml with project change" do
476 put '/issues/3.xml',
477 {:issue => {:project_id => 2, :subject => 'Project changed'}},
478 credentials('jsmith')
594 479
595 480 issue = Issue.find(3)
596 481 assert_equal 2, issue.project_id
597 482 assert_equal 'Project changed', issue.subject
598 483 end
599 end
600
601 context "PUT /issues/6.xml with failed update" do
602 setup do
603 @parameters = {:issue => {:subject => ''}}
604 end
605
606 should "not create a new issue" do
607 assert_no_difference('Issue.count') do
608 put '/issues/6.xml', @parameters, credentials('jsmith')
609 end
610 end
611 484
612 should "not create a new journal" do
613 assert_no_difference('Journal.count') do
614 put '/issues/6.xml', @parameters, credentials('jsmith')
615 end
616 end
617
618 should "have an errors tag" do
619 put '/issues/6.xml', @parameters, credentials('jsmith')
485 test "PUT /issues/:id.xml with failed update" do
486 put '/issues/6.xml', {:issue => {:subject => ''}}, credentials('jsmith')
620 487
488 assert_response :unprocessable_entity
621 489 assert_select 'errors error', :text => "Subject can't be blank"
622 490 end
623 end
624
625 context "PUT /issues/6.json" do
626 setup do
627 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
628 end
629
630 should_allow_api_authentication(:put,
631 '/issues/6.json',
632 {:issue => {:subject => 'API update', :notes => 'A new note'}},
633 {:success_code => :ok})
634 491
635 should "update the issue" do
636 assert_no_difference('Issue.count') do
492 test "PUT /issues/:id.json" do
637 493 assert_difference('Journal.count') do
638 put '/issues/6.json', @parameters, credentials('jsmith')
494 put '/issues/6.json',
495 {:issue => {:subject => 'API update', :notes => 'A new note'}},
496 credentials('jsmith')
639 497
640 498 assert_response :ok
641 499 assert_equal '', response.body
642 500 end
643 end
644 501
645 502 issue = Issue.find(6)
646 503 assert_equal "API update", issue.subject
647 504 journal = Journal.last
648 505 assert_equal "A new note", journal.notes
649 506 end
650 end
651 507
652 context "PUT /issues/6.json with failed update" do
653 should "return errors" do
654 assert_no_difference('Issue.count') do
655 assert_no_difference('Journal.count') do
508 test "PUT /issues/:id.json with failed update" do
656 509 put '/issues/6.json', {:issue => {:subject => ''}}, credentials('jsmith')
657 510
658 511 assert_response :unprocessable_entity
659 end
660 end
661
662 512 json = ActiveSupport::JSON.decode(response.body)
663 513 assert json['errors'].include?("Subject can't be blank")
664 514 end
665 end
666
667 context "DELETE /issues/1.xml" do
668 should_allow_api_authentication(:delete,
669 '/issues/6.xml',
670 {},
671 {:success_code => :ok})
672 515
673 should "delete the issue" do
516 test "DELETE /issues/:id.xml" do
674 517 assert_difference('Issue.count', -1) do
675 518 delete '/issues/6.xml', {}, credentials('jsmith')
676 519
677 520 assert_response :ok
678 521 assert_equal '', response.body
679 522 end
680
681 523 assert_nil Issue.find_by_id(6)
682 524 end
683 end
684 525
685 context "DELETE /issues/1.json" do
686 should_allow_api_authentication(:delete,
687 '/issues/6.json',
688 {},
689 {:success_code => :ok})
690
691 should "delete the issue" do
526 test "DELETE /issues/:id.json" do
692 527 assert_difference('Issue.count', -1) do
693 528 delete '/issues/6.json', {}, credentials('jsmith')
694 529
695 530 assert_response :ok
696 531 assert_equal '', response.body
697 532 end
698
699 533 assert_nil Issue.find_by_id(6)
700 534 end
701 end
702 535
703 536 test "POST /issues/:id/watchers.xml should add watcher" do
704 537 assert_difference 'Watcher.count' do
705 538 post '/issues/1/watchers.xml', {:user_id => 3}, credentials('jsmith')
706 539
707 540 assert_response :ok
708 541 assert_equal '', response.body
709 542 end
710 543 watcher = Watcher.order('id desc').first
711 544 assert_equal Issue.find(1), watcher.watchable
712 545 assert_equal User.find(3), watcher.user
713 546 end
714 547
715 548 test "DELETE /issues/:id/watchers/:user_id.xml should remove watcher" do
716 549 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
717 550
718 551 assert_difference 'Watcher.count', -1 do
719 552 delete '/issues/1/watchers/3.xml', {}, credentials('jsmith')
720 553
721 554 assert_response :ok
722 555 assert_equal '', response.body
723 556 end
724 557 assert_equal false, Issue.find(1).watched_by?(User.find(3))
725 558 end
726 559
727 560 def test_create_issue_with_uploaded_file
728 561 set_tmp_attachments_directory
729 562 # upload the file
730 563 assert_difference 'Attachment.count' do
731 564 post '/uploads.xml', 'test_create_with_upload',
732 565 {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
733 566 assert_response :created
734 567 end
735 568 xml = Hash.from_xml(response.body)
736 569 token = xml['upload']['token']
737 570 attachment = Attachment.order('id DESC').first
738 571
739 572 # create the issue with the upload's token
740 573 assert_difference 'Issue.count' do
741 574 post '/issues.xml',
742 575 {:issue => {:project_id => 1, :subject => 'Uploaded file',
743 576 :uploads => [{:token => token, :filename => 'test.txt',
744 577 :content_type => 'text/plain'}]}},
745 578 credentials('jsmith')
746 579 assert_response :created
747 580 end
748 581 issue = Issue.order('id DESC').first
749 582 assert_equal 1, issue.attachments.count
750 583 assert_equal attachment, issue.attachments.first
751 584
752 585 attachment.reload
753 586 assert_equal 'test.txt', attachment.filename
754 587 assert_equal 'text/plain', attachment.content_type
755 588 assert_equal 'test_create_with_upload'.size, attachment.filesize
756 589 assert_equal 2, attachment.author_id
757 590
758 591 # get the issue with its attachments
759 592 get "/issues/#{issue.id}.xml", :include => 'attachments'
760 593 assert_response :success
761 594 xml = Hash.from_xml(response.body)
762 595 attachments = xml['issue']['attachments']
763 596 assert_kind_of Array, attachments
764 597 assert_equal 1, attachments.size
765 598 url = attachments.first['content_url']
766 599 assert_not_nil url
767 600
768 601 # download the attachment
769 602 get url
770 603 assert_response :success
771 604 end
772 605
773 606 def test_update_issue_with_uploaded_file
774 607 set_tmp_attachments_directory
775 608 # upload the file
776 609 assert_difference 'Attachment.count' do
777 610 post '/uploads.xml', 'test_upload_with_upload',
778 611 {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
779 612 assert_response :created
780 613 end
781 614 xml = Hash.from_xml(response.body)
782 615 token = xml['upload']['token']
783 616 attachment = Attachment.order('id DESC').first
784 617
785 618 # update the issue with the upload's token
786 619 assert_difference 'Journal.count' do
787 620 put '/issues/1.xml',
788 621 {:issue => {:notes => 'Attachment added',
789 622 :uploads => [{:token => token, :filename => 'test.txt',
790 623 :content_type => 'text/plain'}]}},
791 624 credentials('jsmith')
792 625 assert_response :ok
793 626 assert_equal '', @response.body
794 627 end
795 628
796 629 issue = Issue.find(1)
797 630 assert_include attachment, issue.attachments
798 631 end
799 632 end
@@ -1,1271 +1,1236
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class UserTest < ActiveSupport::TestCase
21 21 fixtures :users, :members, :projects, :roles, :member_roles, :auth_sources,
22 22 :trackers, :issue_statuses,
23 23 :projects_trackers,
24 24 :watchers,
25 25 :issue_categories, :enumerations, :issues,
26 26 :journals, :journal_details,
27 27 :groups_users,
28 28 :enabled_modules
29 29
30 30 include Redmine::I18n
31 31
32 32 def setup
33 33 @admin = User.find(1)
34 34 @jsmith = User.find(2)
35 35 @dlopper = User.find(3)
36 36 end
37 37
38 38 def test_sorted_scope_should_sort_user_by_display_name
39 39 # Use .active to ignore anonymous with localized display name
40 40 assert_equal User.active.map(&:name).map(&:downcase).sort,
41 41 User.active.sorted.map(&:name).map(&:downcase)
42 42 end
43 43
44 44 def test_generate
45 45 User.generate!(:firstname => 'Testing connection')
46 46 User.generate!(:firstname => 'Testing connection')
47 47 assert_equal 2, User.where(:firstname => 'Testing connection').count
48 48 end
49 49
50 50 def test_truth
51 51 assert_kind_of User, @jsmith
52 52 end
53 53
54 54 def test_mail_should_be_stripped
55 55 u = User.new
56 56 u.mail = " foo@bar.com "
57 57 assert_equal "foo@bar.com", u.mail
58 58 end
59 59
60 60 def test_mail_validation
61 61 u = User.new
62 62 u.mail = ''
63 63 assert !u.valid?
64 64 assert_include I18n.translate('activerecord.errors.messages.blank'), u.errors[:mail]
65 65 end
66 66
67 67 def test_login_length_validation
68 68 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
69 69 user.login = "x" * (User::LOGIN_LENGTH_LIMIT+1)
70 70 assert !user.valid?
71 71
72 72 user.login = "x" * (User::LOGIN_LENGTH_LIMIT)
73 73 assert user.valid?
74 74 assert user.save
75 75 end
76 76
77 77 def test_generate_password_should_respect_minimum_password_length
78 78 with_settings :password_min_length => 15 do
79 79 user = User.generate!(:generate_password => true)
80 80 assert user.password.length >= 15
81 81 end
82 82 end
83 83
84 84 def test_generate_password_should_not_generate_password_with_less_than_10_characters
85 85 with_settings :password_min_length => 4 do
86 86 user = User.generate!(:generate_password => true)
87 87 assert user.password.length >= 10
88 88 end
89 89 end
90 90
91 91 def test_generate_password_on_create_should_set_password
92 92 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
93 93 user.login = "newuser"
94 94 user.generate_password = true
95 95 assert user.save
96 96
97 97 password = user.password
98 98 assert user.check_password?(password)
99 99 end
100 100
101 101 def test_generate_password_on_update_should_update_password
102 102 user = User.find(2)
103 103 hash = user.hashed_password
104 104 user.generate_password = true
105 105 assert user.save
106 106
107 107 password = user.password
108 108 assert user.check_password?(password)
109 109 assert_not_equal hash, user.reload.hashed_password
110 110 end
111 111
112 112 def test_create
113 113 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
114 114
115 115 user.login = "jsmith"
116 116 user.password, user.password_confirmation = "password", "password"
117 117 # login uniqueness
118 118 assert !user.save
119 119 assert_equal 1, user.errors.count
120 120
121 121 user.login = "newuser"
122 122 user.password, user.password_confirmation = "password", "pass"
123 123 # password confirmation
124 124 assert !user.save
125 125 assert_equal 1, user.errors.count
126 126
127 127 user.password, user.password_confirmation = "password", "password"
128 128 assert user.save
129 129 end
130 130
131 131 def test_user_before_create_should_set_the_mail_notification_to_the_default_setting
132 132 @user1 = User.generate!
133 133 assert_equal 'only_my_events', @user1.mail_notification
134 134 with_settings :default_notification_option => 'all' do
135 135 @user2 = User.generate!
136 136 assert_equal 'all', @user2.mail_notification
137 137 end
138 138 end
139 139
140 140 def test_user_login_should_be_case_insensitive
141 141 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
142 142 u.login = 'newuser'
143 143 u.password, u.password_confirmation = "password", "password"
144 144 assert u.save
145 145 u = User.new(:firstname => "Similar", :lastname => "User",
146 146 :mail => "similaruser@somenet.foo")
147 147 u.login = 'NewUser'
148 148 u.password, u.password_confirmation = "password", "password"
149 149 assert !u.save
150 150 assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:login]
151 151 end
152 152
153 153 def test_mail_uniqueness_should_not_be_case_sensitive
154 154 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
155 155 u.login = 'newuser1'
156 156 u.password, u.password_confirmation = "password", "password"
157 157 assert u.save
158 158
159 159 u = User.new(:firstname => "new", :lastname => "user", :mail => "newUser@Somenet.foo")
160 160 u.login = 'newuser2'
161 161 u.password, u.password_confirmation = "password", "password"
162 162 assert !u.save
163 163 assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:mail]
164 164 end
165 165
166 166 def test_update
167 167 assert_equal "admin", @admin.login
168 168 @admin.login = "john"
169 169 assert @admin.save, @admin.errors.full_messages.join("; ")
170 170 @admin.reload
171 171 assert_equal "john", @admin.login
172 172 end
173 173
174 174 def test_update_should_not_fail_for_legacy_user_with_different_case_logins
175 175 u1 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser1@somenet.foo")
176 176 u1.login = 'newuser1'
177 177 assert u1.save
178 178
179 179 u2 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser2@somenet.foo")
180 180 u2.login = 'newuser1'
181 181 assert u2.save(:validate => false)
182 182
183 183 user = User.find(u2.id)
184 184 user.firstname = "firstname"
185 185 assert user.save, "Save failed"
186 186 end
187 187
188 188 def test_destroy_should_delete_members_and_roles
189 189 members = Member.where(:user_id => 2)
190 190 ms = members.count
191 191 rs = members.collect(&:roles).flatten.size
192 192 assert ms > 0
193 193 assert rs > 0
194 194 assert_difference 'Member.count', - ms do
195 195 assert_difference 'MemberRole.count', - rs do
196 196 User.find(2).destroy
197 197 end
198 198 end
199 199 assert_nil User.find_by_id(2)
200 200 assert_equal 0, Member.where(:user_id => 2).count
201 201 end
202 202
203 203 def test_destroy_should_update_attachments
204 204 attachment = Attachment.create!(:container => Project.find(1),
205 205 :file => uploaded_test_file("testfile.txt", "text/plain"),
206 206 :author_id => 2)
207 207
208 208 User.find(2).destroy
209 209 assert_nil User.find_by_id(2)
210 210 assert_equal User.anonymous, attachment.reload.author
211 211 end
212 212
213 213 def test_destroy_should_update_comments
214 214 comment = Comment.create!(
215 215 :commented => News.create!(:project_id => 1,
216 216 :author_id => 1, :title => 'foo', :description => 'foo'),
217 217 :author => User.find(2),
218 218 :comments => 'foo'
219 219 )
220 220
221 221 User.find(2).destroy
222 222 assert_nil User.find_by_id(2)
223 223 assert_equal User.anonymous, comment.reload.author
224 224 end
225 225
226 226 def test_destroy_should_update_issues
227 227 issue = Issue.create!(:project_id => 1, :author_id => 2,
228 228 :tracker_id => 1, :subject => 'foo')
229 229
230 230 User.find(2).destroy
231 231 assert_nil User.find_by_id(2)
232 232 assert_equal User.anonymous, issue.reload.author
233 233 end
234 234
235 235 def test_destroy_should_unassign_issues
236 236 issue = Issue.create!(:project_id => 1, :author_id => 1,
237 237 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
238 238
239 239 User.find(2).destroy
240 240 assert_nil User.find_by_id(2)
241 241 assert_nil issue.reload.assigned_to
242 242 end
243 243
244 244 def test_destroy_should_update_journals
245 245 issue = Issue.create!(:project_id => 1, :author_id => 2,
246 246 :tracker_id => 1, :subject => 'foo')
247 247 issue.init_journal(User.find(2), "update")
248 248 issue.save!
249 249
250 250 User.find(2).destroy
251 251 assert_nil User.find_by_id(2)
252 252 assert_equal User.anonymous, issue.journals.first.reload.user
253 253 end
254 254
255 255 def test_destroy_should_update_journal_details_old_value
256 256 issue = Issue.create!(:project_id => 1, :author_id => 1,
257 257 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
258 258 issue.init_journal(User.find(1), "update")
259 259 issue.assigned_to_id = nil
260 260 assert_difference 'JournalDetail.count' do
261 261 issue.save!
262 262 end
263 263 journal_detail = JournalDetail.order('id DESC').first
264 264 assert_equal '2', journal_detail.old_value
265 265
266 266 User.find(2).destroy
267 267 assert_nil User.find_by_id(2)
268 268 assert_equal User.anonymous.id.to_s, journal_detail.reload.old_value
269 269 end
270 270
271 271 def test_destroy_should_update_journal_details_value
272 272 issue = Issue.create!(:project_id => 1, :author_id => 1,
273 273 :tracker_id => 1, :subject => 'foo')
274 274 issue.init_journal(User.find(1), "update")
275 275 issue.assigned_to_id = 2
276 276 assert_difference 'JournalDetail.count' do
277 277 issue.save!
278 278 end
279 279 journal_detail = JournalDetail.order('id DESC').first
280 280 assert_equal '2', journal_detail.value
281 281
282 282 User.find(2).destroy
283 283 assert_nil User.find_by_id(2)
284 284 assert_equal User.anonymous.id.to_s, journal_detail.reload.value
285 285 end
286 286
287 287 def test_destroy_should_update_messages
288 288 board = Board.create!(:project_id => 1, :name => 'Board', :description => 'Board')
289 289 message = Message.create!(:board_id => board.id, :author_id => 2,
290 290 :subject => 'foo', :content => 'foo')
291 291 User.find(2).destroy
292 292 assert_nil User.find_by_id(2)
293 293 assert_equal User.anonymous, message.reload.author
294 294 end
295 295
296 296 def test_destroy_should_update_news
297 297 news = News.create!(:project_id => 1, :author_id => 2,
298 298 :title => 'foo', :description => 'foo')
299 299 User.find(2).destroy
300 300 assert_nil User.find_by_id(2)
301 301 assert_equal User.anonymous, news.reload.author
302 302 end
303 303
304 304 def test_destroy_should_delete_private_queries
305 305 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PRIVATE)
306 306 query.project_id = 1
307 307 query.user_id = 2
308 308 query.save!
309 309
310 310 User.find(2).destroy
311 311 assert_nil User.find_by_id(2)
312 312 assert_nil Query.find_by_id(query.id)
313 313 end
314 314
315 315 def test_destroy_should_update_public_queries
316 316 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PUBLIC)
317 317 query.project_id = 1
318 318 query.user_id = 2
319 319 query.save!
320 320
321 321 User.find(2).destroy
322 322 assert_nil User.find_by_id(2)
323 323 assert_equal User.anonymous, query.reload.user
324 324 end
325 325
326 326 def test_destroy_should_update_time_entries
327 327 entry = TimeEntry.new(:hours => '2', :spent_on => Date.today,
328 328 :activity => TimeEntryActivity.create!(:name => 'foo'))
329 329 entry.project_id = 1
330 330 entry.user_id = 2
331 331 entry.save!
332 332
333 333 User.find(2).destroy
334 334 assert_nil User.find_by_id(2)
335 335 assert_equal User.anonymous, entry.reload.user
336 336 end
337 337
338 338 def test_destroy_should_delete_tokens
339 339 token = Token.create!(:user_id => 2, :value => 'foo')
340 340
341 341 User.find(2).destroy
342 342 assert_nil User.find_by_id(2)
343 343 assert_nil Token.find_by_id(token.id)
344 344 end
345 345
346 346 def test_destroy_should_delete_watchers
347 347 issue = Issue.create!(:project_id => 1, :author_id => 1,
348 348 :tracker_id => 1, :subject => 'foo')
349 349 watcher = Watcher.create!(:user_id => 2, :watchable => issue)
350 350
351 351 User.find(2).destroy
352 352 assert_nil User.find_by_id(2)
353 353 assert_nil Watcher.find_by_id(watcher.id)
354 354 end
355 355
356 356 def test_destroy_should_update_wiki_contents
357 357 wiki_content = WikiContent.create!(
358 358 :text => 'foo',
359 359 :author_id => 2,
360 360 :page => WikiPage.create!(:title => 'Foo',
361 361 :wiki => Wiki.create!(:project_id => 3,
362 362 :start_page => 'Start'))
363 363 )
364 364 wiki_content.text = 'bar'
365 365 assert_difference 'WikiContent::Version.count' do
366 366 wiki_content.save!
367 367 end
368 368
369 369 User.find(2).destroy
370 370 assert_nil User.find_by_id(2)
371 371 assert_equal User.anonymous, wiki_content.reload.author
372 372 wiki_content.versions.each do |version|
373 373 assert_equal User.anonymous, version.reload.author
374 374 end
375 375 end
376 376
377 377 def test_destroy_should_nullify_issue_categories
378 378 category = IssueCategory.create!(:project_id => 1, :assigned_to_id => 2, :name => 'foo')
379 379
380 380 User.find(2).destroy
381 381 assert_nil User.find_by_id(2)
382 382 assert_nil category.reload.assigned_to_id
383 383 end
384 384
385 385 def test_destroy_should_nullify_changesets
386 386 changeset = Changeset.create!(
387 387 :repository => Repository::Subversion.create!(
388 388 :project_id => 1,
389 389 :url => 'file:///tmp',
390 390 :identifier => 'tmp'
391 391 ),
392 392 :revision => '12',
393 393 :committed_on => Time.now,
394 394 :committer => 'jsmith'
395 395 )
396 396 assert_equal 2, changeset.user_id
397 397
398 398 User.find(2).destroy
399 399 assert_nil User.find_by_id(2)
400 400 assert_nil changeset.reload.user_id
401 401 end
402 402
403 403 def test_anonymous_user_should_not_be_destroyable
404 404 assert_no_difference 'User.count' do
405 405 assert_equal false, User.anonymous.destroy
406 406 end
407 407 end
408 408
409 409 def test_password_change_should_destroy_tokens
410 410 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
411 411 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
412 412
413 413 user = User.find(2)
414 414 user.password, user.password_confirmation = "a new password", "a new password"
415 415 assert user.save
416 416
417 417 assert_nil Token.find_by_id(recovery_token.id)
418 418 assert_nil Token.find_by_id(autologin_token.id)
419 419 end
420 420
421 421 def test_mail_change_should_destroy_tokens
422 422 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
423 423 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
424 424
425 425 user = User.find(2)
426 426 user.mail = "user@somwehere.com"
427 427 assert user.save
428 428
429 429 assert_nil Token.find_by_id(recovery_token.id)
430 430 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
431 431 end
432 432
433 433 def test_change_on_other_fields_should_not_destroy_tokens
434 434 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
435 435 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
436 436
437 437 user = User.find(2)
438 438 user.firstname = "Bobby"
439 439 assert user.save
440 440
441 441 assert_equal recovery_token, Token.find_by_id(recovery_token.id)
442 442 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
443 443 end
444 444
445 445 def test_validate_login_presence
446 446 @admin.login = ""
447 447 assert !@admin.save
448 448 assert_equal 1, @admin.errors.count
449 449 end
450 450
451 451 def test_validate_mail_notification_inclusion
452 452 u = User.new
453 453 u.mail_notification = 'foo'
454 454 u.save
455 455 assert_not_equal [], u.errors[:mail_notification]
456 456 end
457 457
458 458 def test_password
459 459 user = User.try_to_login("admin", "admin")
460 460 assert_kind_of User, user
461 461 assert_equal "admin", user.login
462 462 user.password = "hello123"
463 463 assert user.save
464 464
465 465 user = User.try_to_login("admin", "hello123")
466 466 assert_kind_of User, user
467 467 assert_equal "admin", user.login
468 468 end
469 469
470 470 def test_validate_password_length
471 471 with_settings :password_min_length => '100' do
472 472 user = User.new(:firstname => "new100",
473 473 :lastname => "user100", :mail => "newuser100@somenet.foo")
474 474 user.login = "newuser100"
475 475 user.password, user.password_confirmation = "password100", "password100"
476 476 assert !user.save
477 477 assert_equal 1, user.errors.count
478 478 end
479 479 end
480 480
481 481 def test_name_format
482 482 assert_equal 'John S.', @jsmith.name(:firstname_lastinitial)
483 483 assert_equal 'Smith, John', @jsmith.name(:lastname_coma_firstname)
484 484 assert_equal 'J. Smith', @jsmith.name(:firstinitial_lastname)
485 485 assert_equal 'J.-P. Lang', User.new(:firstname => 'Jean-Philippe', :lastname => 'Lang').name(:firstinitial_lastname)
486 486 end
487 487
488 488 def test_name_should_use_setting_as_default_format
489 489 with_settings :user_format => :firstname_lastname do
490 490 assert_equal 'John Smith', @jsmith.reload.name
491 491 end
492 492 with_settings :user_format => :username do
493 493 assert_equal 'jsmith', @jsmith.reload.name
494 494 end
495 495 with_settings :user_format => :lastname do
496 496 assert_equal 'Smith', @jsmith.reload.name
497 497 end
498 498 end
499 499
500 500 def test_today_should_return_the_day_according_to_user_time_zone
501 501 preference = User.find(1).pref
502 502 date = Date.new(2012, 05, 15)
503 503 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
504 504 Date.stubs(:today).returns(date)
505 505 Time.stubs(:now).returns(time)
506 506
507 507 preference.update_attribute :time_zone, 'Baku' # UTC+4
508 508 assert_equal '2012-05-16', User.find(1).today.to_s
509 509
510 510 preference.update_attribute :time_zone, 'La Paz' # UTC-4
511 511 assert_equal '2012-05-15', User.find(1).today.to_s
512 512
513 513 preference.update_attribute :time_zone, ''
514 514 assert_equal '2012-05-15', User.find(1).today.to_s
515 515 end
516 516
517 517 def test_time_to_date_should_return_the_date_according_to_user_time_zone
518 518 preference = User.find(1).pref
519 519 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
520 520
521 521 preference.update_attribute :time_zone, 'Baku' # UTC+4
522 522 assert_equal '2012-05-16', User.find(1).time_to_date(time).to_s
523 523
524 524 preference.update_attribute :time_zone, 'La Paz' # UTC-4
525 525 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
526 526
527 527 preference.update_attribute :time_zone, ''
528 528 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
529 529 end
530 530
531 531 def test_fields_for_order_statement_should_return_fields_according_user_format_setting
532 532 with_settings :user_format => 'lastname_coma_firstname' do
533 533 assert_equal ['users.lastname', 'users.firstname', 'users.id'],
534 534 User.fields_for_order_statement
535 535 end
536 536 end
537 537
538 538 def test_fields_for_order_statement_width_table_name_should_prepend_table_name
539 539 with_settings :user_format => 'lastname_firstname' do
540 540 assert_equal ['authors.lastname', 'authors.firstname', 'authors.id'],
541 541 User.fields_for_order_statement('authors')
542 542 end
543 543 end
544 544
545 545 def test_fields_for_order_statement_with_blank_format_should_return_default
546 546 with_settings :user_format => '' do
547 547 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
548 548 User.fields_for_order_statement
549 549 end
550 550 end
551 551
552 552 def test_fields_for_order_statement_with_invalid_format_should_return_default
553 553 with_settings :user_format => 'foo' do
554 554 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
555 555 User.fields_for_order_statement
556 556 end
557 557 end
558 558
559 559 test ".try_to_login with good credentials should return the user" do
560 560 user = User.try_to_login("admin", "admin")
561 561 assert_kind_of User, user
562 562 assert_equal "admin", user.login
563 563 end
564 564
565 565 test ".try_to_login with wrong credentials should return nil" do
566 566 assert_nil User.try_to_login("admin", "foo")
567 567 end
568 568
569 569 def test_try_to_login_with_locked_user_should_return_nil
570 570 @jsmith.status = User::STATUS_LOCKED
571 571 @jsmith.save!
572 572
573 573 user = User.try_to_login("jsmith", "jsmith")
574 574 assert_equal nil, user
575 575 end
576 576
577 577 def test_try_to_login_with_locked_user_and_not_active_only_should_return_user
578 578 @jsmith.status = User::STATUS_LOCKED
579 579 @jsmith.save!
580 580
581 581 user = User.try_to_login("jsmith", "jsmith", false)
582 582 assert_equal @jsmith, user
583 583 end
584 584
585 585 test ".try_to_login should fall-back to case-insensitive if user login is not found as-typed" do
586 586 user = User.try_to_login("AdMin", "admin")
587 587 assert_kind_of User, user
588 588 assert_equal "admin", user.login
589 589 end
590 590
591 591 test ".try_to_login should select the exact matching user first" do
592 592 case_sensitive_user = User.generate! do |user|
593 593 user.password = "admin123"
594 594 end
595 595 # bypass validations to make it appear like existing data
596 596 case_sensitive_user.update_attribute(:login, 'ADMIN')
597 597
598 598 user = User.try_to_login("ADMIN", "admin123")
599 599 assert_kind_of User, user
600 600 assert_equal "ADMIN", user.login
601 601 end
602 602
603 603 if ldap_configured?
604 context "#try_to_login using LDAP" do
605 context "with failed connection to the LDAP server" do
606 should "return nil" do
607 @auth_source = AuthSourceLdap.find(1)
604 test "#try_to_login using LDAP with failed connection to the LDAP server" do
605 auth_source = AuthSourceLdap.find(1)
608 606 AuthSource.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::LdapError, 'Cannot connect')
609 607
610 608 assert_equal nil, User.try_to_login('edavis', 'wrong')
611 609 end
612 end
613 610
614 context "with an unsuccessful authentication" do
615 should "return nil" do
611 test "#try_to_login using LDAP" do
616 612 assert_equal nil, User.try_to_login('edavis', 'wrong')
617 613 end
618 end
619 614
620 context "binding with user's account" do
621 setup do
622 @auth_source = AuthSourceLdap.find(1)
623 @auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
624 @auth_source.account_password = ''
625 @auth_source.save!
615 test "#try_to_login using LDAP binding with user's account" do
616 auth_source = AuthSourceLdap.find(1)
617 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
618 auth_source.account_password = ''
619 auth_source.save!
626 620
627 @ldap_user = User.new(:mail => 'example1@redmine.org', :firstname => 'LDAP', :lastname => 'user', :auth_source_id => 1)
628 @ldap_user.login = 'example1'
629 @ldap_user.save!
630 end
621 ldap_user = User.new(:mail => 'example1@redmine.org', :firstname => 'LDAP', :lastname => 'user', :auth_source_id => 1)
622 ldap_user.login = 'example1'
623 ldap_user.save!
631 624
632 context "with a successful authentication" do
633 should "return the user" do
634 625 assert_equal @ldap_user, User.try_to_login('example1', '123456')
635 end
636 end
637
638 context "with an unsuccessful authentication" do
639 should "return nil" do
640 626 assert_nil User.try_to_login('example1', '11111')
641 627 end
642 end
643 end
644 628
645 context "on the fly registration" do
646 setup do
647 @auth_source = AuthSourceLdap.find(1)
648 @auth_source.update_attribute :onthefly_register, true
649 end
629 test "#try_to_login using LDAP on the fly registration" do
630 AuthSourceLdap.find(1).update_attribute :onthefly_register, true
650 631
651 context "with a successful authentication" do
652 should "create a new user account if it doesn't exist" do
653 632 assert_difference('User.count') do
654 user = User.try_to_login('edavis', '123456')
655 assert !user.admin?
633 assert User.try_to_login('edavis', '123456')
656 634 end
657 end
658
659 should "retrieve existing user" do
660 user = User.try_to_login('edavis', '123456')
661 user.admin = true
662 user.save!
663 635
664 636 assert_no_difference('User.count') do
665 user = User.try_to_login('edavis', '123456')
666 assert user.admin?
667 end
668 end
637 assert User.try_to_login('edavis', '123456')
669 638 end
670 639
671 context "binding with user's account" do
672 setup do
673 @auth_source = AuthSourceLdap.find(1)
674 @auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
675 @auth_source.account_password = ''
676 @auth_source.save!
640 assert_nil User.try_to_login('example1', '11111')
677 641 end
678 642
679 context "with a successful authentication" do
680 should "create a new user account if it doesn't exist" do
643 test "#try_to_login using LDAP on the fly registration and binding with user's account" do
644 auth_source = AuthSourceLdap.find(1)
645 auth_source.update_attribute :onthefly_register, true
646 auth_source = AuthSourceLdap.find(1)
647 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
648 auth_source.account_password = ''
649 auth_source.save!
650
681 651 assert_difference('User.count') do
682 user = User.try_to_login('example1', '123456')
683 assert_kind_of User, user
684 end
652 assert User.try_to_login('example1', '123456')
685 653 end
654
655 assert_no_difference('User.count') do
656 assert User.try_to_login('edavis', '123456')
686 657 end
687 658
688 context "with an unsuccessful authentication" do
689 should "return nil" do
690 659 assert_nil User.try_to_login('example1', '11111')
691 660 end
692 end
693 end
694 end
695 end
696 661
697 662 else
698 663 puts "Skipping LDAP tests."
699 664 end
700 665
701 666 def test_create_anonymous
702 667 AnonymousUser.delete_all
703 668 anon = User.anonymous
704 669 assert !anon.new_record?
705 670 assert_kind_of AnonymousUser, anon
706 671 end
707 672
708 673 def test_ensure_single_anonymous_user
709 674 AnonymousUser.delete_all
710 675 anon1 = User.anonymous
711 676 assert !anon1.new_record?
712 677 assert_kind_of AnonymousUser, anon1
713 678 anon2 = AnonymousUser.create(
714 679 :lastname => 'Anonymous', :firstname => '',
715 680 :mail => '', :login => '', :status => 0)
716 681 assert_equal 1, anon2.errors.count
717 682 end
718 683
719 684 def test_rss_key
720 685 assert_nil @jsmith.rss_token
721 686 key = @jsmith.rss_key
722 687 assert_equal 40, key.length
723 688
724 689 @jsmith.reload
725 690 assert_equal key, @jsmith.rss_key
726 691 end
727 692
728 693 def test_rss_key_should_not_be_generated_twice
729 694 assert_difference 'Token.count', 1 do
730 695 key1 = @jsmith.rss_key
731 696 key2 = @jsmith.rss_key
732 697 assert_equal key1, key2
733 698 end
734 699 end
735 700
736 701 def test_api_key_should_not_be_generated_twice
737 702 assert_difference 'Token.count', 1 do
738 703 key1 = @jsmith.api_key
739 704 key2 = @jsmith.api_key
740 705 assert_equal key1, key2
741 706 end
742 707 end
743 708
744 709 test "#api_key should generate a new one if the user doesn't have one" do
745 710 user = User.generate!(:api_token => nil)
746 711 assert_nil user.api_token
747 712
748 713 key = user.api_key
749 714 assert_equal 40, key.length
750 715 user.reload
751 716 assert_equal key, user.api_key
752 717 end
753 718
754 719 test "#api_key should return the existing api token value" do
755 720 user = User.generate!
756 721 token = Token.create!(:action => 'api')
757 722 user.api_token = token
758 723 assert user.save
759 724
760 725 assert_equal token.value, user.api_key
761 726 end
762 727
763 728 test "#find_by_api_key should return nil if no matching key is found" do
764 729 assert_nil User.find_by_api_key('zzzzzzzzz')
765 730 end
766 731
767 732 test "#find_by_api_key should return nil if the key is found for an inactive user" do
768 733 user = User.generate!
769 734 user.status = User::STATUS_LOCKED
770 735 token = Token.create!(:action => 'api')
771 736 user.api_token = token
772 737 user.save
773 738
774 739 assert_nil User.find_by_api_key(token.value)
775 740 end
776 741
777 742 test "#find_by_api_key should return the user if the key is found for an active user" do
778 743 user = User.generate!
779 744 token = Token.create!(:action => 'api')
780 745 user.api_token = token
781 746 user.save
782 747
783 748 assert_equal user, User.find_by_api_key(token.value)
784 749 end
785 750
786 751 def test_default_admin_account_changed_should_return_false_if_account_was_not_changed
787 752 user = User.find_by_login("admin")
788 753 user.password = "admin"
789 754 assert user.save(:validate => false)
790 755
791 756 assert_equal false, User.default_admin_account_changed?
792 757 end
793 758
794 759 def test_default_admin_account_changed_should_return_true_if_password_was_changed
795 760 user = User.find_by_login("admin")
796 761 user.password = "newpassword"
797 762 user.save!
798 763
799 764 assert_equal true, User.default_admin_account_changed?
800 765 end
801 766
802 767 def test_default_admin_account_changed_should_return_true_if_account_is_disabled
803 768 user = User.find_by_login("admin")
804 769 user.password = "admin"
805 770 user.status = User::STATUS_LOCKED
806 771 assert user.save(:validate => false)
807 772
808 773 assert_equal true, User.default_admin_account_changed?
809 774 end
810 775
811 776 def test_default_admin_account_changed_should_return_true_if_account_does_not_exist
812 777 user = User.find_by_login("admin")
813 778 user.destroy
814 779
815 780 assert_equal true, User.default_admin_account_changed?
816 781 end
817 782
818 783 def test_membership_with_project_should_return_membership
819 784 project = Project.find(1)
820 785
821 786 membership = @jsmith.membership(project)
822 787 assert_kind_of Member, membership
823 788 assert_equal @jsmith, membership.user
824 789 assert_equal project, membership.project
825 790 end
826 791
827 792 def test_membership_with_project_id_should_return_membership
828 793 project = Project.find(1)
829 794
830 795 membership = @jsmith.membership(1)
831 796 assert_kind_of Member, membership
832 797 assert_equal @jsmith, membership.user
833 798 assert_equal project, membership.project
834 799 end
835 800
836 801 def test_membership_for_non_member_should_return_nil
837 802 project = Project.find(1)
838 803
839 804 user = User.generate!
840 805 membership = user.membership(1)
841 806 assert_nil membership
842 807 end
843 808
844 809 def test_roles_for_project_with_member_on_public_project_should_return_roles_and_non_member
845 810 roles = @jsmith.roles_for_project(Project.find(1))
846 811 assert_kind_of Role, roles.first
847 812 assert_equal ["Manager"], roles.map(&:name)
848 813 end
849 814
850 815 def test_roles_for_project_with_member_on_private_project_should_return_roles
851 816 Project.find(1).update_attribute :is_public, false
852 817
853 818 roles = @jsmith.roles_for_project(Project.find(1))
854 819 assert_kind_of Role, roles.first
855 820 assert_equal ["Manager"], roles.map(&:name)
856 821 end
857 822
858 823 def test_roles_for_project_with_non_member_with_public_project_should_return_non_member
859 824 set_language_if_valid 'en'
860 825 roles = User.find(8).roles_for_project(Project.find(1))
861 826 assert_equal ["Non member"], roles.map(&:name)
862 827 end
863 828
864 829 def test_roles_for_project_with_non_member_with_public_project_and_override_should_return_override_roles
865 830 project = Project.find(1)
866 831 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
867 832 roles = User.find(8).roles_for_project(project)
868 833 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
869 834 end
870 835
871 836 def test_roles_for_project_with_non_member_with_private_project_should_return_no_roles
872 837 Project.find(1).update_attribute :is_public, false
873 838
874 839 roles = User.find(8).roles_for_project(Project.find(1))
875 840 assert_equal [], roles.map(&:name)
876 841 end
877 842
878 843 def test_roles_for_project_with_non_member_with_private_project_and_override_should_return_no_roles
879 844 project = Project.find(1)
880 845 project.update_attribute :is_public, false
881 846 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
882 847 roles = User.find(8).roles_for_project(project)
883 848 assert_equal [], roles.map(&:name).sort
884 849 end
885 850
886 851 def test_roles_for_project_with_anonymous_with_public_project_should_return_anonymous
887 852 set_language_if_valid 'en'
888 853 roles = User.anonymous.roles_for_project(Project.find(1))
889 854 assert_equal ["Anonymous"], roles.map(&:name)
890 855 end
891 856
892 857 def test_roles_for_project_with_anonymous_with_public_project_and_override_should_return_override_roles
893 858 project = Project.find(1)
894 859 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
895 860 roles = User.anonymous.roles_for_project(project)
896 861 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
897 862 end
898 863
899 864 def test_roles_for_project_with_anonymous_with_private_project_should_return_no_roles
900 865 Project.find(1).update_attribute :is_public, false
901 866
902 867 roles = User.anonymous.roles_for_project(Project.find(1))
903 868 assert_equal [], roles.map(&:name)
904 869 end
905 870
906 871 def test_roles_for_project_with_anonymous_with_private_project_and_override_should_return_no_roles
907 872 project = Project.find(1)
908 873 project.update_attribute :is_public, false
909 874 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
910 875 roles = User.anonymous.roles_for_project(project)
911 876 assert_equal [], roles.map(&:name).sort
912 877 end
913 878
914 879 def test_projects_by_role_for_user_with_role
915 880 user = User.find(2)
916 881 assert_kind_of Hash, user.projects_by_role
917 882 assert_equal 2, user.projects_by_role.size
918 883 assert_equal [1,5], user.projects_by_role[Role.find(1)].collect(&:id).sort
919 884 assert_equal [2], user.projects_by_role[Role.find(2)].collect(&:id).sort
920 885 end
921 886
922 887 def test_accessing_projects_by_role_with_no_projects_should_return_an_empty_array
923 888 user = User.find(2)
924 889 assert_equal [], user.projects_by_role[Role.find(3)]
925 890 # should not update the hash
926 891 assert_nil user.projects_by_role.values.detect(&:blank?)
927 892 end
928 893
929 894 def test_projects_by_role_for_user_with_no_role
930 895 user = User.generate!
931 896 assert_equal({}, user.projects_by_role)
932 897 end
933 898
934 899 def test_projects_by_role_for_anonymous
935 900 assert_equal({}, User.anonymous.projects_by_role)
936 901 end
937 902
938 903 def test_valid_notification_options
939 904 # without memberships
940 905 assert_equal 5, User.find(7).valid_notification_options.size
941 906 # with memberships
942 907 assert_equal 6, User.find(2).valid_notification_options.size
943 908 end
944 909
945 910 def test_valid_notification_options_class_method
946 911 assert_equal 5, User.valid_notification_options.size
947 912 assert_equal 5, User.valid_notification_options(User.find(7)).size
948 913 assert_equal 6, User.valid_notification_options(User.find(2)).size
949 914 end
950 915
951 916 def test_notified_project_ids_setter_should_coerce_to_unique_integer_array
952 917 @jsmith.notified_project_ids = ["1", "123", "2u", "wrong", "12", 6, 12, -35, ""]
953 918 assert_equal [1, 123, 2, 12, 6], @jsmith.notified_projects_ids
954 919 end
955 920
956 921 def test_mail_notification_all
957 922 @jsmith.mail_notification = 'all'
958 923 @jsmith.notified_project_ids = []
959 924 @jsmith.save
960 925 @jsmith.reload
961 926 assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
962 927 end
963 928
964 929 def test_mail_notification_selected
965 930 @jsmith.mail_notification = 'selected'
966 931 @jsmith.notified_project_ids = [1]
967 932 @jsmith.save
968 933 @jsmith.reload
969 934 assert Project.find(1).recipients.include?(@jsmith.mail)
970 935 end
971 936
972 937 def test_mail_notification_only_my_events
973 938 @jsmith.mail_notification = 'only_my_events'
974 939 @jsmith.notified_project_ids = []
975 940 @jsmith.save
976 941 @jsmith.reload
977 942 assert !@jsmith.projects.first.recipients.include?(@jsmith.mail)
978 943 end
979 944
980 945 def test_comments_sorting_preference
981 946 assert !@jsmith.wants_comments_in_reverse_order?
982 947 @jsmith.pref.comments_sorting = 'asc'
983 948 assert !@jsmith.wants_comments_in_reverse_order?
984 949 @jsmith.pref.comments_sorting = 'desc'
985 950 assert @jsmith.wants_comments_in_reverse_order?
986 951 end
987 952
988 953 def test_find_by_mail_should_be_case_insensitive
989 954 u = User.find_by_mail('JSmith@somenet.foo')
990 955 assert_not_nil u
991 956 assert_equal 'jsmith@somenet.foo', u.mail
992 957 end
993 958
994 959 def test_random_password
995 960 u = User.new
996 961 u.random_password
997 962 assert !u.password.blank?
998 963 assert !u.password_confirmation.blank?
999 964 end
1000 965
1001 966 test "#change_password_allowed? should be allowed if no auth source is set" do
1002 967 user = User.generate!
1003 968 assert user.change_password_allowed?
1004 969 end
1005 970
1006 971 test "#change_password_allowed? should delegate to the auth source" do
1007 972 user = User.generate!
1008 973
1009 974 allowed_auth_source = AuthSource.generate!
1010 975 def allowed_auth_source.allow_password_changes?; true; end
1011 976
1012 977 denied_auth_source = AuthSource.generate!
1013 978 def denied_auth_source.allow_password_changes?; false; end
1014 979
1015 980 assert user.change_password_allowed?
1016 981
1017 982 user.auth_source = allowed_auth_source
1018 983 assert user.change_password_allowed?, "User not allowed to change password, though auth source does"
1019 984
1020 985 user.auth_source = denied_auth_source
1021 986 assert !user.change_password_allowed?, "User allowed to change password, though auth source does not"
1022 987 end
1023 988
1024 989 def test_own_account_deletable_should_be_true_with_unsubscrive_enabled
1025 990 with_settings :unsubscribe => '1' do
1026 991 assert_equal true, User.find(2).own_account_deletable?
1027 992 end
1028 993 end
1029 994
1030 995 def test_own_account_deletable_should_be_false_with_unsubscrive_disabled
1031 996 with_settings :unsubscribe => '0' do
1032 997 assert_equal false, User.find(2).own_account_deletable?
1033 998 end
1034 999 end
1035 1000
1036 1001 def test_own_account_deletable_should_be_false_for_a_single_admin
1037 1002 User.delete_all(["admin = ? AND id <> ?", true, 1])
1038 1003
1039 1004 with_settings :unsubscribe => '1' do
1040 1005 assert_equal false, User.find(1).own_account_deletable?
1041 1006 end
1042 1007 end
1043 1008
1044 1009 def test_own_account_deletable_should_be_true_for_an_admin_if_other_admin_exists
1045 1010 User.generate! do |user|
1046 1011 user.admin = true
1047 1012 end
1048 1013
1049 1014 with_settings :unsubscribe => '1' do
1050 1015 assert_equal true, User.find(1).own_account_deletable?
1051 1016 end
1052 1017 end
1053 1018
1054 1019 context "#allowed_to?" do
1055 1020 context "with a unique project" do
1056 1021 should "return false if project is archived" do
1057 1022 project = Project.find(1)
1058 1023 Project.any_instance.stubs(:status).returns(Project::STATUS_ARCHIVED)
1059 1024 assert_equal false, @admin.allowed_to?(:view_issues, Project.find(1))
1060 1025 end
1061 1026
1062 1027 should "return false for write action if project is closed" do
1063 1028 project = Project.find(1)
1064 1029 Project.any_instance.stubs(:status).returns(Project::STATUS_CLOSED)
1065 1030 assert_equal false, @admin.allowed_to?(:edit_project, Project.find(1))
1066 1031 end
1067 1032
1068 1033 should "return true for read action if project is closed" do
1069 1034 project = Project.find(1)
1070 1035 Project.any_instance.stubs(:status).returns(Project::STATUS_CLOSED)
1071 1036 assert_equal true, @admin.allowed_to?(:view_project, Project.find(1))
1072 1037 end
1073 1038
1074 1039 should "return false if related module is disabled" do
1075 1040 project = Project.find(1)
1076 1041 project.enabled_module_names = ["issue_tracking"]
1077 1042 assert_equal true, @admin.allowed_to?(:add_issues, project)
1078 1043 assert_equal false, @admin.allowed_to?(:view_wiki_pages, project)
1079 1044 end
1080 1045
1081 1046 should "authorize nearly everything for admin users" do
1082 1047 project = Project.find(1)
1083 1048 assert ! @admin.member_of?(project)
1084 1049 %w(edit_issues delete_issues manage_news add_documents manage_wiki).each do |p|
1085 1050 assert_equal true, @admin.allowed_to?(p.to_sym, project)
1086 1051 end
1087 1052 end
1088 1053
1089 1054 should "authorize normal users depending on their roles" do
1090 1055 project = Project.find(1)
1091 1056 assert_equal true, @jsmith.allowed_to?(:delete_messages, project) #Manager
1092 1057 assert_equal false, @dlopper.allowed_to?(:delete_messages, project) #Developper
1093 1058 end
1094 1059 end
1095 1060
1096 1061 context "with multiple projects" do
1097 1062 should "return false if array is empty" do
1098 1063 assert_equal false, @admin.allowed_to?(:view_project, [])
1099 1064 end
1100 1065
1101 1066 should "return true only if user has permission on all these projects" do
1102 1067 assert_equal true, @admin.allowed_to?(:view_project, Project.all.to_a)
1103 1068 assert_equal false, @dlopper.allowed_to?(:view_project, Project.all.to_a) #cannot see Project(2)
1104 1069 assert_equal true, @jsmith.allowed_to?(:edit_issues, @jsmith.projects.to_a) #Manager or Developer everywhere
1105 1070 assert_equal false, @jsmith.allowed_to?(:delete_issue_watchers, @jsmith.projects.to_a) #Dev cannot delete_issue_watchers
1106 1071 end
1107 1072
1108 1073 should "behave correctly with arrays of 1 project" do
1109 1074 assert_equal false, User.anonymous.allowed_to?(:delete_issues, [Project.first])
1110 1075 end
1111 1076 end
1112 1077
1113 1078 context "with options[:global]" do
1114 1079 should "authorize if user has at least one role that has this permission" do
1115 1080 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1116 1081 @anonymous = User.find(6)
1117 1082 assert_equal true, @jsmith.allowed_to?(:delete_issue_watchers, nil, :global => true)
1118 1083 assert_equal false, @dlopper2.allowed_to?(:delete_issue_watchers, nil, :global => true)
1119 1084 assert_equal true, @dlopper2.allowed_to?(:add_issues, nil, :global => true)
1120 1085 assert_equal false, @anonymous.allowed_to?(:add_issues, nil, :global => true)
1121 1086 assert_equal true, @anonymous.allowed_to?(:view_issues, nil, :global => true)
1122 1087 end
1123 1088 end
1124 1089 end
1125 1090
1126 1091 # this is just a proxy method, the test only calls it to ensure it doesn't break trivially
1127 1092 context "#allowed_to_globally?" do
1128 1093 should "proxy to #allowed_to? and reflect global permissions" do
1129 1094 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1130 1095 @anonymous = User.find(6)
1131 1096 assert_equal true, @jsmith.allowed_to_globally?(:delete_issue_watchers)
1132 1097 assert_equal false, @dlopper2.allowed_to_globally?(:delete_issue_watchers)
1133 1098 assert_equal true, @dlopper2.allowed_to_globally?(:add_issues)
1134 1099 assert_equal false, @anonymous.allowed_to_globally?(:add_issues)
1135 1100 assert_equal true, @anonymous.allowed_to_globally?(:view_issues)
1136 1101 end
1137 1102 end
1138 1103
1139 1104 context "User#notify_about?" do
1140 1105 context "Issues" do
1141 1106 setup do
1142 1107 @project = Project.find(1)
1143 1108 @author = User.generate!
1144 1109 @assignee = User.generate!
1145 1110 @issue = Issue.generate!(:project => @project, :assigned_to => @assignee, :author => @author)
1146 1111 end
1147 1112
1148 1113 should "be true for a user with :all" do
1149 1114 @author.update_attribute(:mail_notification, 'all')
1150 1115 assert @author.notify_about?(@issue)
1151 1116 end
1152 1117
1153 1118 should "be false for a user with :none" do
1154 1119 @author.update_attribute(:mail_notification, 'none')
1155 1120 assert ! @author.notify_about?(@issue)
1156 1121 end
1157 1122
1158 1123 should "be false for a user with :only_my_events and isn't an author, creator, or assignee" do
1159 1124 @user = User.generate!(:mail_notification => 'only_my_events')
1160 1125 Member.create!(:user => @user, :project => @project, :role_ids => [1])
1161 1126 assert ! @user.notify_about?(@issue)
1162 1127 end
1163 1128
1164 1129 should "be true for a user with :only_my_events and is the author" do
1165 1130 @author.update_attribute(:mail_notification, 'only_my_events')
1166 1131 assert @author.notify_about?(@issue)
1167 1132 end
1168 1133
1169 1134 should "be true for a user with :only_my_events and is the assignee" do
1170 1135 @assignee.update_attribute(:mail_notification, 'only_my_events')
1171 1136 assert @assignee.notify_about?(@issue)
1172 1137 end
1173 1138
1174 1139 should "be true for a user with :only_assigned and is the assignee" do
1175 1140 @assignee.update_attribute(:mail_notification, 'only_assigned')
1176 1141 assert @assignee.notify_about?(@issue)
1177 1142 end
1178 1143
1179 1144 should "be false for a user with :only_assigned and is not the assignee" do
1180 1145 @author.update_attribute(:mail_notification, 'only_assigned')
1181 1146 assert ! @author.notify_about?(@issue)
1182 1147 end
1183 1148
1184 1149 should "be true for a user with :only_owner and is the author" do
1185 1150 @author.update_attribute(:mail_notification, 'only_owner')
1186 1151 assert @author.notify_about?(@issue)
1187 1152 end
1188 1153
1189 1154 should "be false for a user with :only_owner and is not the author" do
1190 1155 @assignee.update_attribute(:mail_notification, 'only_owner')
1191 1156 assert ! @assignee.notify_about?(@issue)
1192 1157 end
1193 1158
1194 1159 should "be true for a user with :selected and is the author" do
1195 1160 @author.update_attribute(:mail_notification, 'selected')
1196 1161 assert @author.notify_about?(@issue)
1197 1162 end
1198 1163
1199 1164 should "be true for a user with :selected and is the assignee" do
1200 1165 @assignee.update_attribute(:mail_notification, 'selected')
1201 1166 assert @assignee.notify_about?(@issue)
1202 1167 end
1203 1168
1204 1169 should "be false for a user with :selected and is not the author or assignee" do
1205 1170 @user = User.generate!(:mail_notification => 'selected')
1206 1171 Member.create!(:user => @user, :project => @project, :role_ids => [1])
1207 1172 assert ! @user.notify_about?(@issue)
1208 1173 end
1209 1174 end
1210 1175 end
1211 1176
1212 1177 def test_notify_about_news
1213 1178 user = User.generate!
1214 1179 news = News.new
1215 1180
1216 1181 User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
1217 1182 user.mail_notification = option
1218 1183 assert_equal (option != 'none'), user.notify_about?(news)
1219 1184 end
1220 1185 end
1221 1186
1222 1187 def test_salt_unsalted_passwords
1223 1188 # Restore a user with an unsalted password
1224 1189 user = User.find(1)
1225 1190 user.salt = nil
1226 1191 user.hashed_password = User.hash_password("unsalted")
1227 1192 user.save!
1228 1193
1229 1194 User.salt_unsalted_passwords!
1230 1195
1231 1196 user.reload
1232 1197 # Salt added
1233 1198 assert !user.salt.blank?
1234 1199 # Password still valid
1235 1200 assert user.check_password?("unsalted")
1236 1201 assert_equal user, User.try_to_login(user.login, "unsalted")
1237 1202 end
1238 1203
1239 1204 if Object.const_defined?(:OpenID)
1240 1205 def test_setting_identity_url
1241 1206 normalized_open_id_url = 'http://example.com/'
1242 1207 u = User.new( :identity_url => 'http://example.com/' )
1243 1208 assert_equal normalized_open_id_url, u.identity_url
1244 1209 end
1245 1210
1246 1211 def test_setting_identity_url_without_trailing_slash
1247 1212 normalized_open_id_url = 'http://example.com/'
1248 1213 u = User.new( :identity_url => 'http://example.com' )
1249 1214 assert_equal normalized_open_id_url, u.identity_url
1250 1215 end
1251 1216
1252 1217 def test_setting_identity_url_without_protocol
1253 1218 normalized_open_id_url = 'http://example.com/'
1254 1219 u = User.new( :identity_url => 'example.com' )
1255 1220 assert_equal normalized_open_id_url, u.identity_url
1256 1221 end
1257 1222
1258 1223 def test_setting_blank_identity_url
1259 1224 u = User.new( :identity_url => 'example.com' )
1260 1225 u.identity_url = ''
1261 1226 assert u.identity_url.blank?
1262 1227 end
1263 1228
1264 1229 def test_setting_invalid_identity_url
1265 1230 u = User.new( :identity_url => 'this is not an openid url' )
1266 1231 assert u.identity_url.blank?
1267 1232 end
1268 1233 else
1269 1234 puts "Skipping openid tests."
1270 1235 end
1271 1236 end
General Comments 0
You need to be logged in to leave comments. Login now