To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / .svn / pristine / 44 / 448dc5ae56acac81ffaeeeb288586a6544fe08b0.svn-base @ 1297:0a574315af3e

History | View | Annotate | Download (18.7 KB)

1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
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
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

    
18
require File.expand_path('../../test_helper', __FILE__)
19
require 'projects_controller'
20

    
21
# Re-raise errors caught by the controller.
22
class ProjectsController; def rescue_action(e) raise e end; end
23

    
24
class ProjectsControllerTest < ActionController::TestCase
25
  fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
26
           :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
27
           :attachments, :custom_fields, :custom_values, :time_entries
28

    
29
  def setup
30
    @controller = ProjectsController.new
31
    @request    = ActionController::TestRequest.new
32
    @response   = ActionController::TestResponse.new
33
    @request.session[:user_id] = nil
34
    Setting.default_language = 'en'
35
  end
36

    
37
  def test_index
38
    get :index
39
    assert_response :success
40
    assert_template 'index'
41
    assert_not_nil assigns(:projects)
42

    
43
    assert_tag :ul, :child => {:tag => 'li',
44
                               :descendant => {:tag => 'a', :content => 'eCookbook'},
45
                               :child => { :tag => 'ul',
46
                                           :descendant => { :tag => 'a',
47
                                                            :content => 'Child of private child'
48
                                                           }
49
                                          }
50
                               }
51

    
52
    assert_no_tag :a, :content => /Private child of eCookbook/
53
  end
54

    
55
  def test_index_atom
56
    get :index, :format => 'atom'
57
    assert_response :success
58
    assert_template 'common/feed.atom'
59
    assert_select 'feed>title', :text => 'Redmine: Latest projects'
60
    assert_select 'feed>entry', :count => Project.count(:conditions => Project.visible_condition(User.current))
61
  end
62

    
63
  context "#index" do
64
    context "by non-admin user with view_time_entries permission" do
65
      setup do
66
        @request.session[:user_id] = 3
67
      end
68
      should "show overall spent time link" do
69
        get :index
70
        assert_template 'index'
71
        assert_tag :a, :attributes => {:href => '/time_entries'}
72
      end
73
    end
74

    
75
    context "by non-admin user without view_time_entries permission" do
76
      setup do
77
        Role.find(2).remove_permission! :view_time_entries
78
        Role.non_member.remove_permission! :view_time_entries
79
        Role.anonymous.remove_permission! :view_time_entries
80
        @request.session[:user_id] = 3
81
      end
82
      should "not show overall spent time link" do
83
        get :index
84
        assert_template 'index'
85
        assert_no_tag :a, :attributes => {:href => '/time_entries'}
86
      end
87
    end
88
  end
89

    
90
  context "#new" do
91
    context "by admin user" do
92
      setup do
93
        @request.session[:user_id] = 1
94
      end
95

    
96
      should "accept get" do
97
        get :new
98
        assert_response :success
99
        assert_template 'new'
100
      end
101

    
102
    end
103

    
104
    context "by non-admin user with add_project permission" do
105
      setup do
106
        Role.non_member.add_permission! :add_project
107
        @request.session[:user_id] = 9
108
      end
109

    
110
      should "accept get" do
111
        get :new
112
        assert_response :success
113
        assert_template 'new'
114
        assert_no_tag :select, :attributes => {:name => 'project[parent_id]'}
115
      end
116
    end
117

    
118
    context "by non-admin user with add_subprojects permission" do
119
      setup do
120
        Role.find(1).remove_permission! :add_project
121
        Role.find(1).add_permission! :add_subprojects
122
        @request.session[:user_id] = 2
123
      end
124

    
125
      should "accept get" do
126
        get :new, :parent_id => 'ecookbook'
127
        assert_response :success
128
        assert_template 'new'
129
        # parent project selected
130
        assert_tag :select, :attributes => {:name => 'project[parent_id]'},
131
                            :child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}}
132
        # no empty value
133
        assert_no_tag :select, :attributes => {:name => 'project[parent_id]'},
134
                               :child => {:tag => 'option', :attributes => {:value => ''}}
135
      end
136
    end
137

    
138
  end
139

    
140
  context "POST :create" do
141
    context "by admin user" do
142
      setup do
143
        @request.session[:user_id] = 1
144
      end
145

    
146
      should "create a new project" do
147
        post :create,
148
          :project => {
149
            :name => "blog",
150
            :description => "weblog",
151
            :homepage => 'http://weblog',
152
            :identifier => "blog",
153
            :is_public => 1,
154
            :custom_field_values => { '3' => 'Beta' },
155
            :tracker_ids => ['1', '3'],
156
            # an issue custom field that is not for all project
157
            :issue_custom_field_ids => ['9'],
158
            :enabled_module_names => ['issue_tracking', 'news', 'repository']
159
          }
160
        assert_redirected_to '/projects/blog/settings'
161

    
162
        project = Project.find_by_name('blog')
163
        assert_kind_of Project, project
164
        assert project.active?
165
        assert_equal 'weblog', project.description
166
        assert_equal 'http://weblog', project.homepage
167
        assert_equal true, project.is_public?
168
        assert_nil project.parent
169
        assert_equal 'Beta', project.custom_value_for(3).value
170
        assert_equal [1, 3], project.trackers.map(&:id).sort
171
        assert_equal ['issue_tracking', 'news', 'repository'], project.enabled_module_names.sort
172
        assert project.issue_custom_fields.include?(IssueCustomField.find(9))
173
      end
174

    
175
      should "create a new subproject" do
176
        post :create, :project => { :name => "blog",
177
                                 :description => "weblog",
178
                                 :identifier => "blog",
179
                                 :is_public => 1,
180
                                 :custom_field_values => { '3' => 'Beta' },
181
                                 :parent_id => 1
182
                                }
183
        assert_redirected_to '/projects/blog/settings'
184

    
185
        project = Project.find_by_name('blog')
186
        assert_kind_of Project, project
187
        assert_equal Project.find(1), project.parent
188
      end
189

    
190
      should "continue" do
191
        assert_difference 'Project.count' do
192
          post :create, :project => {:name => "blog", :identifier => "blog"}, :continue => 'Create and continue'
193
        end
194
        assert_redirected_to '/projects/new?'
195
      end
196
    end
197

    
198
    context "by non-admin user with add_project permission" do
199
      setup do
200
        Role.non_member.add_permission! :add_project
201
        @request.session[:user_id] = 9
202
      end
203

    
204
      should "accept create a Project" do
205
        post :create, :project => { :name => "blog",
206
                                 :description => "weblog",
207
                                 :identifier => "blog",
208
                                 :is_public => 1,
209
                                 :custom_field_values => { '3' => 'Beta' },
210
                                 :tracker_ids => ['1', '3'],
211
                                 :enabled_module_names => ['issue_tracking', 'news', 'repository']
212
                                }
213

    
214
        assert_redirected_to '/projects/blog/settings'
215

    
216
        project = Project.find_by_name('blog')
217
        assert_kind_of Project, project
218
        assert_equal 'weblog', project.description
219
        assert_equal true, project.is_public?
220
        assert_equal [1, 3], project.trackers.map(&:id).sort
221
        assert_equal ['issue_tracking', 'news', 'repository'], project.enabled_module_names.sort
222

    
223
        # User should be added as a project member
224
        assert User.find(9).member_of?(project)
225
        assert_equal 1, project.members.size
226
      end
227

    
228
      should "fail with parent_id" do
229
        assert_no_difference 'Project.count' do
230
          post :create, :project => { :name => "blog",
231
                                   :description => "weblog",
232
                                   :identifier => "blog",
233
                                   :is_public => 1,
234
                                   :custom_field_values => { '3' => 'Beta' },
235
                                   :parent_id => 1
236
                                  }
237
        end
238
        assert_response :success
239
        project = assigns(:project)
240
        assert_kind_of Project, project
241
        assert_not_nil project.errors[:parent_id]
242
      end
243
    end
244

    
245
    context "by non-admin user with add_subprojects permission" do
246
      setup do
247
        Role.find(1).remove_permission! :add_project
248
        Role.find(1).add_permission! :add_subprojects
249
        @request.session[:user_id] = 2
250
      end
251

    
252
      should "create a project with a parent_id" do
253
        post :create, :project => { :name => "blog",
254
                                 :description => "weblog",
255
                                 :identifier => "blog",
256
                                 :is_public => 1,
257
                                 :custom_field_values => { '3' => 'Beta' },
258
                                 :parent_id => 1
259
                                }
260
        assert_redirected_to '/projects/blog/settings'
261
        project = Project.find_by_name('blog')
262
      end
263

    
264
      should "fail without parent_id" do
265
        assert_no_difference 'Project.count' do
266
          post :create, :project => { :name => "blog",
267
                                   :description => "weblog",
268
                                   :identifier => "blog",
269
                                   :is_public => 1,
270
                                   :custom_field_values => { '3' => 'Beta' }
271
                                  }
272
        end
273
        assert_response :success
274
        project = assigns(:project)
275
        assert_kind_of Project, project
276
        assert_not_nil project.errors[:parent_id]
277
      end
278

    
279
      should "fail with unauthorized parent_id" do
280
        assert !User.find(2).member_of?(Project.find(6))
281
        assert_no_difference 'Project.count' do
282
          post :create, :project => { :name => "blog",
283
                                   :description => "weblog",
284
                                   :identifier => "blog",
285
                                   :is_public => 1,
286
                                   :custom_field_values => { '3' => 'Beta' },
287
                                   :parent_id => 6
288
                                  }
289
        end
290
        assert_response :success
291
        project = assigns(:project)
292
        assert_kind_of Project, project
293
        assert_not_nil project.errors[:parent_id]
294
      end
295
    end
296
  end
297

    
298
  def test_create_should_preserve_modules_on_validation_failure
299
    with_settings :default_projects_modules => ['issue_tracking', 'repository'] do
300
      @request.session[:user_id] = 1
301
      assert_no_difference 'Project.count' do
302
        post :create, :project => {
303
          :name => "blog",
304
          :identifier => "",
305
          :enabled_module_names => %w(issue_tracking news)
306
        }
307
      end
308
      assert_response :success
309
      project = assigns(:project)
310
      assert_equal %w(issue_tracking news), project.enabled_module_names.sort
311
    end
312
  end
313

    
314
  def test_create_should_not_accept_get
315
    @request.session[:user_id] = 1
316
    get :create
317
    assert_response :method_not_allowed
318
  end
319

    
320
  def test_show_by_id
321
    get :show, :id => 1
322
    assert_response :success
323
    assert_template 'show'
324
    assert_not_nil assigns(:project)
325
  end
326

    
327
  def test_show_by_identifier
328
    get :show, :id => 'ecookbook'
329
    assert_response :success
330
    assert_template 'show'
331
    assert_not_nil assigns(:project)
332
    assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
333

    
334
    assert_tag 'li', :content => /Development status/
335
  end
336

    
337
  def test_show_should_not_display_hidden_custom_fields
338
    ProjectCustomField.find_by_name('Development status').update_attribute :visible, false
339
    get :show, :id => 'ecookbook'
340
    assert_response :success
341
    assert_template 'show'
342
    assert_not_nil assigns(:project)
343

    
344
    assert_no_tag 'li', :content => /Development status/
345
  end
346

    
347
  def test_show_should_not_fail_when_custom_values_are_nil
348
    project = Project.find_by_identifier('ecookbook')
349
    project.custom_values.first.update_attribute(:value, nil)
350
    get :show, :id => 'ecookbook'
351
    assert_response :success
352
    assert_template 'show'
353
    assert_not_nil assigns(:project)
354
    assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
355
  end
356

    
357
  def show_archived_project_should_be_denied
358
    project = Project.find_by_identifier('ecookbook')
359
    project.archive!
360

    
361
    get :show, :id => 'ecookbook'
362
    assert_response 403
363
    assert_nil assigns(:project)
364
    assert_tag :tag => 'p', :content => /archived/
365
  end
366

    
367
  def test_private_subprojects_hidden
368
    get :show, :id => 'ecookbook'
369
    assert_response :success
370
    assert_template 'show'
371
    assert_no_tag :tag => 'a', :content => /Private child/
372
  end
373

    
374
  def test_private_subprojects_visible
375
    @request.session[:user_id] = 2 # manager who is a member of the private subproject
376
    get :show, :id => 'ecookbook'
377
    assert_response :success
378
    assert_template 'show'
379
    assert_tag :tag => 'a', :content => /Private child/
380
  end
381

    
382
  def test_settings
383
    @request.session[:user_id] = 2 # manager
384
    get :settings, :id => 1
385
    assert_response :success
386
    assert_template 'settings'
387
  end
388

    
389
  def test_update
390
    @request.session[:user_id] = 2 # manager
391
    post :update, :id => 1, :project => {:name => 'Test changed name',
392
                                       :issue_custom_field_ids => ['']}
393
    assert_redirected_to '/projects/ecookbook/settings'
394
    project = Project.find(1)
395
    assert_equal 'Test changed name', project.name
396
  end
397

    
398
  def test_modules
399
    @request.session[:user_id] = 2
400
    Project.find(1).enabled_module_names = ['issue_tracking', 'news']
401

    
402
    post :modules, :id => 1, :enabled_module_names => ['issue_tracking', 'repository', 'documents']
403
    assert_redirected_to '/projects/ecookbook/settings/modules'
404
    assert_equal ['documents', 'issue_tracking', 'repository'], Project.find(1).enabled_module_names.sort
405
  end
406

    
407
  def test_modules_should_not_allow_get
408
    @request.session[:user_id] = 1
409
    get :modules, :id => 1
410
    assert_response :method_not_allowed
411
  end
412

    
413
  def test_get_destroy
414
    @request.session[:user_id] = 1 # admin
415
    get :destroy, :id => 1
416
    assert_response :success
417
    assert_template 'destroy'
418
    assert_not_nil Project.find_by_id(1)
419
  end
420

    
421
  def test_post_destroy
422
    @request.session[:user_id] = 1 # admin
423
    post :destroy, :id => 1, :confirm => 1
424
    assert_redirected_to '/admin/projects'
425
    assert_nil Project.find_by_id(1)
426
  end
427

    
428
  def test_archive
429
    @request.session[:user_id] = 1 # admin
430
    post :archive, :id => 1
431
    assert_redirected_to '/admin/projects'
432
    assert !Project.find(1).active?
433
  end
434

    
435
  def test_unarchive
436
    @request.session[:user_id] = 1 # admin
437
    Project.find(1).archive
438
    post :unarchive, :id => 1
439
    assert_redirected_to '/admin/projects'
440
    assert Project.find(1).active?
441
  end
442

    
443
  def test_project_breadcrumbs_should_be_limited_to_3_ancestors
444
    CustomField.delete_all
445
    parent = nil
446
    6.times do |i|
447
      p = Project.create!(:name => "Breadcrumbs #{i}", :identifier => "breadcrumbs-#{i}")
448
      p.set_parent!(parent)
449
      get :show, :id => p
450
      assert_tag :h1, :parent => { :attributes => {:id => 'header'}},
451
                      :children => { :count => [i, 3].min,
452
                                     :only => { :tag => 'a' } }
453

    
454
      parent = p
455
    end
456
  end
457

    
458
  def test_get_copy
459
    @request.session[:user_id] = 1 # admin
460
    get :copy, :id => 1
461
    assert_response :success
462
    assert_template 'copy'
463
    assert assigns(:project)
464
    assert_equal Project.find(1).description, assigns(:project).description
465
    assert_nil assigns(:project).id
466

    
467
    assert_tag :tag => 'input',
468
      :attributes => {:name => 'project[enabled_module_names][]', :value => 'issue_tracking'}
469
  end
470

    
471
  def test_get_copy_without_project
472
    @request.session[:user_id] = 1 # admin
473
    get :copy
474
    assert_response :redirect
475
    assert_redirected_to :controller => 'admin', :action => 'projects'
476
  end
477

    
478
  def test_post_copy_should_copy_requested_items
479
    @request.session[:user_id] = 1 # admin
480
    CustomField.delete_all
481

    
482
    assert_difference 'Project.count' do
483
      post :copy, :id => 1,
484
        :project => {
485
          :name => 'Copy',
486
          :identifier => 'unique-copy',
487
          :tracker_ids => ['1', '2', '3', ''],
488
          :enabled_module_names => %w(issue_tracking time_tracking)
489
        },
490
        :only => %w(issues versions)
491
    end
492
    project = Project.find('unique-copy')
493
    source = Project.find(1)
494
    assert_equal %w(issue_tracking time_tracking), project.enabled_module_names.sort
495

    
496
    assert_equal source.versions.count, project.versions.count, "All versions were not copied"
497
    # issues assigned to a closed version won't be copied
498
    assert_equal source.issues.select {|i| i.fixed_version.nil? || i.fixed_version.open?}.size,
499
                 project.issues.count, "All issues were not copied"
500
    assert_equal 0, project.members.count
501
  end
502

    
503
  def test_post_copy_should_redirect_to_settings_when_successful
504
    @request.session[:user_id] = 1 # admin
505
    post :copy, :id => 1, :project => {:name => 'Copy', :identifier => 'unique-copy'}
506
    assert_response :redirect
507
    assert_redirected_to :controller => 'projects', :action => 'settings', :id => 'unique-copy'
508
  end
509

    
510
  def test_jump_should_redirect_to_active_tab
511
    get :show, :id => 1, :jump => 'issues'
512
    assert_redirected_to '/projects/ecookbook/issues'
513
  end
514

    
515
  def test_jump_should_not_redirect_to_inactive_tab
516
    get :show, :id => 3, :jump => 'documents'
517
    assert_response :success
518
    assert_template 'show'
519
  end
520

    
521
  def test_jump_should_not_redirect_to_unknown_tab
522
    get :show, :id => 3, :jump => 'foobar'
523
    assert_response :success
524
    assert_template 'show'
525
  end
526

    
527
  # A hook that is manually registered later
528
  class ProjectBasedTemplate < Redmine::Hook::ViewListener
529
    def view_layouts_base_html_head(context)
530
      # Adds a project stylesheet
531
      stylesheet_link_tag(context[:project].identifier) if context[:project]
532
    end
533
  end
534
  # Don't use this hook now
535
  Redmine::Hook.clear_listeners
536

    
537
  def test_hook_response
538
    Redmine::Hook.add_listener(ProjectBasedTemplate)
539
    get :show, :id => 1
540
    assert_tag :tag => 'link', :attributes => {:href => '/stylesheets/ecookbook.css'},
541
                               :parent => {:tag => 'head'}
542

    
543
    Redmine::Hook.clear_listeners
544
  end
545
end