Revision 1297:0a574315af3e .svn/pristine/11

View differences:

.svn/pristine/11/11389dcb8c49b70343e3b80fa2a021abf64753ca.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2012  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

  
20
class RoutingContextMenusTest < ActionController::IntegrationTest
21
  def test_context_menus_time_entries
22
    ["get", "post"].each do |method|
23
      assert_routing(
24
          { :method => method, :path => "/time_entries/context_menu" },
25
          { :controller => 'context_menus', :action => 'time_entries' }
26
        )
27
    end
28
  end
29

  
30
  def test_context_menus_issues
31
    ["get", "post"].each do |method|
32
      assert_routing(
33
          { :method => method, :path => "/issues/context_menu" },
34
          { :controller => 'context_menus', :action => 'issues' }
35
        )
36
    end
37
  end
38
end
.svn/pristine/11/1143136ec6943c91201441e4e743a0264ddfa810.svn-base
1
<%= form_tag({:action => 'edit', :tab => 'mail_handler'}) do %>
2

  
3
<div class="box tabular settings">
4
  <p>
5
    <%= setting_text_area :mail_handler_body_delimiters, :rows => 5 %>
6
    <em class="info"><%= l(:text_line_separated) %></em>
7
  </p>
8
</div>
9

  
10
<div class="box tabular settings">
11
<p><%= setting_check_box :mail_handler_api_enabled,
12
         :onclick => "if (this.checked) { $('#settings_mail_handler_api_key').removeAttr('disabled'); } else { $('#settings_mail_handler_api_key').attr('disabled', true); }"%></p>
13

  
14
<p><%= setting_text_field :mail_handler_api_key, :size => 30,
15
                                                 :id => 'settings_mail_handler_api_key',
16
                                                 :disabled => !Setting.mail_handler_api_enabled? %>
17
  <%= link_to_function l(:label_generate_key), "if (!$('#settings_mail_handler_api_key').attr('disabled')) { $('#settings_mail_handler_api_key').val(randomKey(20)) }" %>
18
</p>
19
</div>
20

  
21
<%= submit_tag l(:button_save) %>
22

  
23
<% end %>
.svn/pristine/11/115477077313264feb09635aa1e17387b5e3f9d3.svn-base
1
require File.expand_path('../../test_helper', __FILE__)
2

  
3
class ContextMenusControllerTest < ActionController::TestCase
4
  fixtures :projects,
5
           :trackers,
6
           :projects_trackers,
7
           :roles,
8
           :member_roles,
9
           :members,
10
           :enabled_modules,
11
           :workflows,
12
           :journals, :journal_details,
13
           :versions,
14
           :issues, :issue_statuses, :issue_categories,
15
           :users,
16
           :enumerations,
17
           :time_entries
18

  
19
  def test_context_menu_one_issue
20
    @request.session[:user_id] = 2
21
    get :issues, :ids => [1]
22
    assert_response :success
23
    assert_template 'context_menu'
24
    assert_tag :tag => 'a', :content => 'Edit',
25
                            :attributes => { :href => '/issues/1/edit',
26
                                             :class => 'icon-edit' }
27
    assert_tag :tag => 'a', :content => 'Closed',
28
                            :attributes => { :href => '/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bstatus_id%5D=5',
29
                                             :class => '' }
30
    assert_tag :tag => 'a', :content => 'Immediate',
31
                            :attributes => { :href => '/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bpriority_id%5D=8',
32
                                             :class => '' }
33
    assert_no_tag :tag => 'a', :content => 'Inactive Priority'
34
    # Versions
35
    assert_tag :tag => 'a', :content => '2.0',
36
                            :attributes => { :href => '/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=3',
37
                                             :class => '' }
38
    assert_tag :tag => 'a', :content => 'eCookbook Subproject 1 - 2.0',
39
                            :attributes => { :href => '/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=4',
40
                                             :class => '' }
41

  
42
    assert_tag :tag => 'a', :content => 'Dave Lopper',
43
                            :attributes => { :href => '/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bassigned_to_id%5D=3',
44
                                             :class => '' }
45
    assert_tag :tag => 'a', :content => 'Copy',
46
                            :attributes => { :href => '/projects/ecookbook/issues/1/copy',
47
                                             :class => 'icon-copy' }
48
    assert_no_tag :tag => 'a', :content => 'Move'
49
    assert_tag :tag => 'a', :content => 'Delete',
50
                            :attributes => { :href => '/issues?ids%5B%5D=1',
51
                                             :class => 'icon-del' }
52
  end
53

  
54
  def test_context_menu_one_issue_by_anonymous
55
    get :issues, :ids => [1]
56
    assert_response :success
57
    assert_template 'context_menu'
58
    assert_tag :tag => 'a', :content => 'Delete',
59
                            :attributes => { :href => '#',
60
                                             :class => 'icon-del disabled' }
61
  end
62

  
63
  def test_context_menu_multiple_issues_of_same_project
64
    @request.session[:user_id] = 2
65
    get :issues, :ids => [1, 2]
66
    assert_response :success
67
    assert_template 'context_menu'
68
    assert_not_nil assigns(:issues)
69
    assert_equal [1, 2], assigns(:issues).map(&:id).sort
70

  
71
    ids = assigns(:issues).map(&:id).sort.map {|i| "ids%5B%5D=#{i}"}.join('&amp;')
72
    assert_tag :tag => 'a', :content => 'Edit',
73
                            :attributes => { :href => "/issues/bulk_edit?#{ids}",
74
                                             :class => 'icon-edit' }
75
    assert_tag :tag => 'a', :content => 'Closed',
76
                            :attributes => { :href => "/issues/bulk_update?#{ids}&amp;issue%5Bstatus_id%5D=5",
77
                                             :class => '' }
78
    assert_tag :tag => 'a', :content => 'Immediate',
79
                            :attributes => { :href => "/issues/bulk_update?#{ids}&amp;issue%5Bpriority_id%5D=8",
80
                                             :class => '' }
81
    assert_tag :tag => 'a', :content => 'Dave Lopper',
82
                            :attributes => { :href => "/issues/bulk_update?#{ids}&amp;issue%5Bassigned_to_id%5D=3",
83
                                             :class => '' }
84
    assert_tag :tag => 'a', :content => 'Copy',
85
                            :attributes => { :href => "/issues/bulk_edit?copy=1&amp;#{ids}",
86
                                             :class => 'icon-copy' }
87
    assert_no_tag :tag => 'a', :content => 'Move'
88
    assert_tag :tag => 'a', :content => 'Delete',
89
                            :attributes => { :href => "/issues?#{ids}",
90
                                             :class => 'icon-del' }
91
  end
92

  
93
  def test_context_menu_multiple_issues_of_different_projects
94
    @request.session[:user_id] = 2
95
    get :issues, :ids => [1, 2, 6]
96
    assert_response :success
97
    assert_template 'context_menu'
98
    assert_not_nil assigns(:issues)
99
    assert_equal [1, 2, 6], assigns(:issues).map(&:id).sort
100

  
101
    ids = assigns(:issues).map(&:id).sort.map {|i| "ids%5B%5D=#{i}"}.join('&amp;')
102
    assert_tag :tag => 'a', :content => 'Edit',
103
                            :attributes => { :href => "/issues/bulk_edit?#{ids}",
104
                                             :class => 'icon-edit' }
105
    assert_tag :tag => 'a', :content => 'Closed',
106
                            :attributes => { :href => "/issues/bulk_update?#{ids}&amp;issue%5Bstatus_id%5D=5",
107
                                             :class => '' }
108
    assert_tag :tag => 'a', :content => 'Immediate',
109
                            :attributes => { :href => "/issues/bulk_update?#{ids}&amp;issue%5Bpriority_id%5D=8",
110
                                             :class => '' }
111
    assert_tag :tag => 'a', :content => 'John Smith',
112
                            :attributes => { :href => "/issues/bulk_update?#{ids}&amp;issue%5Bassigned_to_id%5D=2",
113
                                             :class => '' }
114
    assert_tag :tag => 'a', :content => 'Delete',
115
                            :attributes => { :href => "/issues?#{ids}",
116
                                             :class => 'icon-del' }
117
  end
118

  
119
  def test_context_menu_should_include_list_custom_fields
120
    field = IssueCustomField.create!(:name => 'List', :field_format => 'list',
121
      :possible_values => ['Foo', 'Bar'], :is_for_all => true, :tracker_ids => [1, 2, 3])
122
    @request.session[:user_id] = 2
123
    get :issues, :ids => [1]
124

  
125
    assert_tag 'a',
126
      :content => 'List',
127
      :attributes => {:href => '#'},
128
      :sibling => {:tag => 'ul', :children => {:count => 3}}
129

  
130
    assert_tag 'a',
131
      :content => 'Foo',
132
      :attributes => {:href => "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=Foo"}
133
    assert_tag 'a',
134
      :content => 'none',
135
      :attributes => {:href => "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D="}
136
  end
137

  
138
  def test_context_menu_should_not_include_null_value_for_required_custom_fields
139
    field = IssueCustomField.create!(:name => 'List', :is_required => true, :field_format => 'list',
140
      :possible_values => ['Foo', 'Bar'], :is_for_all => true, :tracker_ids => [1, 2, 3])
141
    @request.session[:user_id] = 2
142
    get :issues, :ids => [1, 2]
143

  
144
    assert_tag 'a',
145
      :content => 'List',
146
      :attributes => {:href => '#'},
147
      :sibling => {:tag => 'ul', :children => {:count => 2}}
148
  end
149

  
150
  def test_context_menu_on_single_issue_should_select_current_custom_field_value
151
    field = IssueCustomField.create!(:name => 'List', :field_format => 'list',
152
      :possible_values => ['Foo', 'Bar'], :is_for_all => true, :tracker_ids => [1, 2, 3])
153
    issue = Issue.find(1)
154
    issue.custom_field_values = {field.id => 'Bar'}
155
    issue.save!
156
    @request.session[:user_id] = 2
157
    get :issues, :ids => [1]
158

  
159
    assert_tag 'a',
160
      :content => 'List',
161
      :attributes => {:href => '#'},
162
      :sibling => {:tag => 'ul', :children => {:count => 3}}
163
    assert_tag 'a',
164
      :content => 'Bar',
165
      :attributes => {:class => /icon-checked/}
166
  end
167

  
168
  def test_context_menu_should_include_bool_custom_fields
169
    field = IssueCustomField.create!(:name => 'Bool', :field_format => 'bool',
170
      :is_for_all => true, :tracker_ids => [1, 2, 3])
171
    @request.session[:user_id] = 2
172
    get :issues, :ids => [1]
173

  
174
    assert_tag 'a',
175
      :content => 'Bool',
176
      :attributes => {:href => '#'},
177
      :sibling => {:tag => 'ul', :children => {:count => 3}}
178

  
179
    assert_tag 'a',
180
      :content => 'Yes',
181
      :attributes => {:href => "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=1"}
182
  end
183

  
184
  def test_context_menu_should_include_user_custom_fields
185
    field = IssueCustomField.create!(:name => 'User', :field_format => 'user',
186
      :is_for_all => true, :tracker_ids => [1, 2, 3])
187
    @request.session[:user_id] = 2
188
    get :issues, :ids => [1]
189

  
190
    assert_tag 'a',
191
      :content => 'User',
192
      :attributes => {:href => '#'},
193
      :sibling => {:tag => 'ul', :children => {:count => Project.find(1).members.count + 1}}
194

  
195
    assert_tag 'a',
196
      :content => 'John Smith',
197
      :attributes => {:href => "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=2"}
198
  end
199

  
200
  def test_context_menu_should_include_version_custom_fields
201
    field = IssueCustomField.create!(:name => 'Version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1, 2, 3])
202
    @request.session[:user_id] = 2
203
    get :issues, :ids => [1]
204

  
205
    assert_tag 'a',
206
      :content => 'Version',
207
      :attributes => {:href => '#'},
208
      :sibling => {:tag => 'ul', :children => {:count => Project.find(1).shared_versions.count + 1}}
209

  
210
    assert_tag 'a',
211
      :content => '2.0',
212
      :attributes => {:href => "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=3"}
213
  end
214

  
215
  def test_context_menu_by_assignable_user_should_include_assigned_to_me_link
216
    @request.session[:user_id] = 2
217
    get :issues, :ids => [1]
218
    assert_response :success
219
    assert_template 'context_menu'
220

  
221
    assert_tag :tag => 'a', :content => / me /,
222
                            :attributes => { :href => '/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bassigned_to_id%5D=2',
223
                                             :class => '' }
224
  end
225

  
226
  def test_context_menu_should_propose_shared_versions_for_issues_from_different_projects
227
    @request.session[:user_id] = 2
228
    version = Version.create!(:name => 'Shared', :sharing => 'system', :project_id => 1)
229

  
230
    get :issues, :ids => [1, 4]
231
    assert_response :success
232
    assert_template 'context_menu'
233

  
234
    assert_include version, assigns(:versions)
235
    assert_tag :tag => 'a', :content => 'eCookbook - Shared'
236
  end
237

  
238
  def test_context_menu_issue_visibility
239
    get :issues, :ids => [1, 4]
240
    assert_response :success
241
    assert_template 'context_menu'
242
    assert_equal [1], assigns(:issues).collect(&:id)
243
  end
244
  
245
  def test_time_entries_context_menu
246
    @request.session[:user_id] = 2
247
    get :time_entries, :ids => [1, 2]
248
    assert_response :success
249
    assert_template 'time_entries'
250
    assert_tag 'a', :content => 'Edit'
251
    assert_no_tag 'a', :content => 'Edit', :attributes => {:class => /disabled/}
252
  end
253
  
254
  def test_time_entries_context_menu_without_edit_permission
255
    @request.session[:user_id] = 2
256
    Role.find_by_name('Manager').remove_permission! :edit_time_entries
257
    
258
    get :time_entries, :ids => [1, 2]
259
    assert_response :success
260
    assert_template 'time_entries'
261
    assert_tag 'a', :content => 'Edit', :attributes => {:class => /disabled/}
262
  end
263
end
.svn/pristine/11/1155c5733fc69fa605b0b34e8b29755f3beb4693.svn-base
1
<%= form_for(:user, :url => { :action => 'update' }, :html => {:method => :put}) do %>
2
<div class="box">
3
<% Group.all.sort.each do |group| %>
4
<label><%= check_box_tag 'user[group_ids][]', group.id, @user.groups.include?(group) %> <%=h group %></label><br />
5
<% end %>
6
<%= hidden_field_tag 'user[group_ids][]', '' %>
7
</div>
8
<%= submit_tag l(:button_save) %>
9
<% end %>
.svn/pristine/11/11a5507f6b6077a6e73fb852952ddb0da8dc089e.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2012  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

  
20
class CustomFieldVersionFormatTest < ActiveSupport::TestCase
21
  fixtures :custom_fields, :projects, :members, :users, :member_roles, :trackers, :issues, :versions
22

  
23
  def setup
24
    @field = IssueCustomField.create!(:name => 'Tester', :field_format => 'version')
25
  end
26

  
27
  def test_possible_values_with_no_arguments
28
    assert_equal [], @field.possible_values
29
    assert_equal [], @field.possible_values(nil)
30
  end
31

  
32
  def test_possible_values_with_project_resource
33
    project = Project.find(1)
34
    possible_values = @field.possible_values(project.issues.first)
35
    assert possible_values.any?
36
    assert_equal project.shared_versions.sort.collect(&:id).map(&:to_s), possible_values
37
  end
38

  
39
  def test_possible_values_with_nil_project_resource
40
    assert_equal [], @field.possible_values(Issue.new)
41
  end
42

  
43
  def test_possible_values_options_with_no_arguments
44
    assert_equal [], @field.possible_values_options
45
    assert_equal [], @field.possible_values_options(nil)
46
  end
47

  
48
  def test_possible_values_options_with_project_resource
49
    project = Project.find(1)
50
    possible_values_options = @field.possible_values_options(project.issues.first)
51
    assert possible_values_options.any?
52
    assert_equal project.shared_versions.sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
53
  end
54

  
55
  def test_possible_values_options_with_array
56
    projects = Project.find([1, 2])
57
    possible_values_options = @field.possible_values_options(projects)
58
    assert possible_values_options.any?
59
    assert_equal (projects.first.shared_versions & projects.last.shared_versions).sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
60
  end
61

  
62
  def test_cast_blank_value
63
    assert_equal nil, @field.cast_value(nil)
64
    assert_equal nil, @field.cast_value("")
65
  end
66

  
67
  def test_cast_valid_value
68
    version = @field.cast_value("2")
69
    assert_kind_of Version, version
70
    assert_equal Version.find(2), version
71
  end
72

  
73
  def test_cast_invalid_value
74
    assert_equal nil, @field.cast_value("187")
75
  end
76
end
.svn/pristine/11/11c49a871d148b89615d8c37f2abca7b6149921b.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2012  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

  
20
class IssueNestedSetTest < ActiveSupport::TestCase
21
  fixtures :projects, :users, :members, :member_roles, :roles,
22
           :trackers, :projects_trackers,
23
           :versions,
24
           :issue_statuses, :issue_categories, :issue_relations, :workflows,
25
           :enumerations,
26
           :issues,
27
           :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
28
           :time_entries
29

  
30
  def test_create_root_issue
31
    issue1 = Issue.generate!
32
    issue2 = Issue.generate!
33
    issue1.reload
34
    issue2.reload
35

  
36
    assert_equal [issue1.id, nil, 1, 2], [issue1.root_id, issue1.parent_id, issue1.lft, issue1.rgt]
37
    assert_equal [issue2.id, nil, 1, 2], [issue2.root_id, issue2.parent_id, issue2.lft, issue2.rgt]
38
  end
39

  
40
  def test_create_child_issue
41
    parent = Issue.generate!
42
    child =  Issue.generate!(:parent_issue_id => parent.id)
43
    parent.reload
44
    child.reload
45

  
46
    assert_equal [parent.id, nil, 1, 4], [parent.root_id, parent.parent_id, parent.lft, parent.rgt]
47
    assert_equal [parent.id, parent.id, 2, 3], [child.root_id, child.parent_id, child.lft, child.rgt]
48
  end
49

  
50
  def test_creating_a_child_in_a_subproject_should_validate
51
    issue = Issue.generate!
52
    child = Issue.new(:project_id => 3, :tracker_id => 2, :author_id => 1,
53
                      :subject => 'child', :parent_issue_id => issue.id)
54
    assert_save child
55
    assert_equal issue, child.reload.parent
56
  end
57

  
58
  def test_creating_a_child_in_an_invalid_project_should_not_validate
59
    issue = Issue.generate!
60
    child = Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
61
                      :subject => 'child', :parent_issue_id => issue.id)
62
    assert !child.save
63
    assert_not_nil child.errors[:parent_issue_id]
64
  end
65

  
66
  def test_move_a_root_to_child
67
    parent1 = Issue.generate!
68
    parent2 = Issue.generate!
69
    child = Issue.generate!(:parent_issue_id => parent1.id)
70

  
71
    parent2.parent_issue_id = parent1.id
72
    parent2.save!
73
    child.reload
74
    parent1.reload
75
    parent2.reload
76

  
77
    assert_equal [parent1.id, 1, 6], [parent1.root_id, parent1.lft, parent1.rgt]
78
    assert_equal [parent1.id, 4, 5], [parent2.root_id, parent2.lft, parent2.rgt]
79
    assert_equal [parent1.id, 2, 3], [child.root_id, child.lft, child.rgt]
80
  end
81

  
82
  def test_move_a_child_to_root
83
    parent1 = Issue.generate!
84
    parent2 = Issue.generate!
85
    child =   Issue.generate!(:parent_issue_id => parent1.id)
86

  
87
    child.parent_issue_id = nil
88
    child.save!
89
    child.reload
90
    parent1.reload
91
    parent2.reload
92

  
93
    assert_equal [parent1.id, 1, 2], [parent1.root_id, parent1.lft, parent1.rgt]
94
    assert_equal [parent2.id, 1, 2], [parent2.root_id, parent2.lft, parent2.rgt]
95
    assert_equal [child.id, 1, 2], [child.root_id, child.lft, child.rgt]
96
  end
97

  
98
  def test_move_a_child_to_another_issue
99
    parent1 = Issue.generate!
100
    parent2 = Issue.generate!
101
    child =   Issue.generate!(:parent_issue_id => parent1.id)
102

  
103
    child.parent_issue_id = parent2.id
104
    child.save!
105
    child.reload
106
    parent1.reload
107
    parent2.reload
108

  
109
    assert_equal [parent1.id, 1, 2], [parent1.root_id, parent1.lft, parent1.rgt]
110
    assert_equal [parent2.id, 1, 4], [parent2.root_id, parent2.lft, parent2.rgt]
111
    assert_equal [parent2.id, 2, 3], [child.root_id, child.lft, child.rgt]
112
  end
113

  
114
  def test_move_a_child_with_descendants_to_another_issue
115
    parent1 = Issue.generate!
116
    parent2 = Issue.generate!
117
    child =   Issue.generate!(:parent_issue_id => parent1.id)
118
    grandchild = Issue.generate!(:parent_issue_id => child.id)
119

  
120
    parent1.reload
121
    parent2.reload
122
    child.reload
123
    grandchild.reload
124

  
125
    assert_equal [parent1.id, 1, 6], [parent1.root_id, parent1.lft, parent1.rgt]
126
    assert_equal [parent2.id, 1, 2], [parent2.root_id, parent2.lft, parent2.rgt]
127
    assert_equal [parent1.id, 2, 5], [child.root_id, child.lft, child.rgt]
128
    assert_equal [parent1.id, 3, 4], [grandchild.root_id, grandchild.lft, grandchild.rgt]
129

  
130
    child.reload.parent_issue_id = parent2.id
131
    child.save!
132
    child.reload
133
    grandchild.reload
134
    parent1.reload
135
    parent2.reload
136

  
137
    assert_equal [parent1.id, 1, 2], [parent1.root_id, parent1.lft, parent1.rgt]
138
    assert_equal [parent2.id, 1, 6], [parent2.root_id, parent2.lft, parent2.rgt]
139
    assert_equal [parent2.id, 2, 5], [child.root_id, child.lft, child.rgt]
140
    assert_equal [parent2.id, 3, 4], [grandchild.root_id, grandchild.lft, grandchild.rgt]
141
  end
142

  
143
  def test_move_a_child_with_descendants_to_another_project
144
    parent1 = Issue.generate!
145
    child =   Issue.generate!(:parent_issue_id => parent1.id)
146
    grandchild = Issue.generate!(:parent_issue_id => child.id)
147

  
148
    child.reload
149
    child.project = Project.find(2)
150
    assert child.save
151
    child.reload
152
    grandchild.reload
153
    parent1.reload
154

  
155
    assert_equal [1, parent1.id, 1, 2], [parent1.project_id, parent1.root_id, parent1.lft, parent1.rgt]
156
    assert_equal [2, child.id, 1, 4], [child.project_id, child.root_id, child.lft, child.rgt]
157
    assert_equal [2, child.id, 2, 3], [grandchild.project_id, grandchild.root_id, grandchild.lft, grandchild.rgt]
158
  end
159

  
160
  def test_moving_an_issue_to_a_descendant_should_not_validate
161
    parent1 = Issue.generate!
162
    parent2 = Issue.generate!
163
    child =   Issue.generate!(:parent_issue_id => parent1.id)
164
    grandchild = Issue.generate!(:parent_issue_id => child.id)
165

  
166
    child.reload
167
    child.parent_issue_id = grandchild.id
168
    assert !child.save
169
    assert_not_nil child.errors[:parent_issue_id]
170
  end
171

  
172
  def test_moving_an_issue_should_keep_valid_relations_only
173
    issue1 = Issue.generate!
174
    issue2 = Issue.generate!
175
    issue3 = Issue.generate!(:parent_issue_id => issue2.id)
176
    issue4 = Issue.generate!
177
    r1 = IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
178
    r2 = IssueRelation.create!(:issue_from => issue1, :issue_to => issue3, :relation_type => IssueRelation::TYPE_PRECEDES)
179
    r3 = IssueRelation.create!(:issue_from => issue2, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES)
180
    issue2.reload
181
    issue2.parent_issue_id = issue1.id
182
    issue2.save!
183
    assert !IssueRelation.exists?(r1.id)
184
    assert !IssueRelation.exists?(r2.id)
185
    assert IssueRelation.exists?(r3.id)
186
  end
187

  
188
  def test_destroy_should_destroy_children
189
    issue1 = Issue.generate!
190
    issue2 = Issue.generate!
191
    issue3 = Issue.generate!(:parent_issue_id => issue2.id)
192
    issue4 = Issue.generate!(:parent_issue_id => issue1.id)
193

  
194
    issue3.init_journal(User.find(2))
195
    issue3.subject = 'child with journal'
196
    issue3.save!
197

  
198
    assert_difference 'Issue.count', -2 do
199
      assert_difference 'Journal.count', -1 do
200
        assert_difference 'JournalDetail.count', -1 do
201
          Issue.find(issue2.id).destroy
202
        end
203
      end
204
    end
205

  
206
    issue1.reload
207
    issue4.reload
208
    assert !Issue.exists?(issue2.id)
209
    assert !Issue.exists?(issue3.id)
210
    assert_equal [issue1.id, 1, 4], [issue1.root_id, issue1.lft, issue1.rgt]
211
    assert_equal [issue1.id, 2, 3], [issue4.root_id, issue4.lft, issue4.rgt]
212
  end
213
  
214
  def test_destroy_child_should_update_parent
215
    issue = Issue.generate!
216
    child1 = Issue.generate!(:parent_issue_id => issue.id)
217
    child2 = Issue.generate!(:parent_issue_id => issue.id)
218
    
219
    issue.reload
220
    assert_equal [issue.id, 1, 6], [issue.root_id, issue.lft, issue.rgt]
221
    
222
    child2.reload.destroy
223
    
224
    issue.reload
225
    assert_equal [issue.id, 1, 4], [issue.root_id, issue.lft, issue.rgt]
226
  end
227

  
228
  def test_destroy_parent_issue_updated_during_children_destroy
229
    parent = Issue.generate!
230
    Issue.generate!(:start_date => Date.today, :parent_issue_id => parent.id)
231
    Issue.generate!(:start_date => 2.days.from_now, :parent_issue_id => parent.id)
232

  
233
    assert_difference 'Issue.count', -3 do
234
      Issue.find(parent.id).destroy
235
    end
236
  end
237

  
238
  def test_destroy_child_issue_with_children
239
    root = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'root')
240
    child = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => root.id)
241
    leaf = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'leaf', :parent_issue_id => child.id)
242
    leaf.init_journal(User.find(2))
243
    leaf.subject = 'leaf with journal'
244
    leaf.save!
245

  
246
    assert_difference 'Issue.count', -2 do
247
      assert_difference 'Journal.count', -1 do
248
        assert_difference 'JournalDetail.count', -1 do
249
          Issue.find(child.id).destroy
250
        end
251
      end
252
    end
253

  
254
    root = Issue.find(root.id)
255
    assert root.leaf?, "Root issue is not a leaf (lft: #{root.lft}, rgt: #{root.rgt})"
256
  end
257

  
258
  def test_destroy_issue_with_grand_child
259
    parent = Issue.generate!
260
    issue = Issue.generate!(:parent_issue_id => parent.id)
261
    child = Issue.generate!(:parent_issue_id => issue.id)
262
    grandchild1 = Issue.generate!(:parent_issue_id => child.id)
263
    grandchild2 = Issue.generate!(:parent_issue_id => child.id)
264

  
265
    assert_difference 'Issue.count', -4 do
266
      Issue.find(issue.id).destroy
267
      parent.reload
268
      assert_equal [1, 2], [parent.lft, parent.rgt]
269
    end
270
  end
271

  
272
  def test_parent_priority_should_be_the_highest_child_priority
273
    parent = Issue.generate!(:priority => IssuePriority.find_by_name('Normal'))
274
    # Create children
275
    child1 = Issue.generate!(:priority => IssuePriority.find_by_name('High'), :parent_issue_id => parent.id)
276
    assert_equal 'High', parent.reload.priority.name
277
    child2 = Issue.generate!(:priority => IssuePriority.find_by_name('Immediate'), :parent_issue_id => child1.id)
278
    assert_equal 'Immediate', child1.reload.priority.name
279
    assert_equal 'Immediate', parent.reload.priority.name
280
    child3 = Issue.generate!(:priority => IssuePriority.find_by_name('Low'), :parent_issue_id => parent.id)
281
    assert_equal 'Immediate', parent.reload.priority.name
282
    # Destroy a child
283
    child1.destroy
284
    assert_equal 'Low', parent.reload.priority.name
285
    # Update a child
286
    child3.reload.priority = IssuePriority.find_by_name('Normal')
287
    child3.save!
288
    assert_equal 'Normal', parent.reload.priority.name
289
  end
290

  
291
  def test_parent_dates_should_be_lowest_start_and_highest_due_dates
292
    parent = Issue.generate!
293
    Issue.generate!(:start_date => '2010-01-25', :due_date => '2010-02-15', :parent_issue_id => parent.id)
294
    Issue.generate!(                             :due_date => '2010-02-13', :parent_issue_id => parent.id)
295
    Issue.generate!(:start_date => '2010-02-01', :due_date => '2010-02-22', :parent_issue_id => parent.id)
296
    parent.reload
297
    assert_equal Date.parse('2010-01-25'), parent.start_date
298
    assert_equal Date.parse('2010-02-22'), parent.due_date
299
  end
300

  
301
  def test_parent_done_ratio_should_be_average_done_ratio_of_leaves
302
    parent = Issue.generate!
303
    Issue.generate!(:done_ratio => 20, :parent_issue_id => parent.id)
304
    assert_equal 20, parent.reload.done_ratio
305
    Issue.generate!(:done_ratio => 70, :parent_issue_id => parent.id)
306
    assert_equal 45, parent.reload.done_ratio
307

  
308
    child = Issue.generate!(:done_ratio => 0, :parent_issue_id => parent.id)
309
    assert_equal 30, parent.reload.done_ratio
310

  
311
    Issue.generate!(:done_ratio => 30, :parent_issue_id => child.id)
312
    assert_equal 30, child.reload.done_ratio
313
    assert_equal 40, parent.reload.done_ratio
314
  end
315

  
316
  def test_parent_done_ratio_should_be_weighted_by_estimated_times_if_any
317
    parent = Issue.generate!
318
    Issue.generate!(:estimated_hours => 10, :done_ratio => 20, :parent_issue_id => parent.id)
319
    assert_equal 20, parent.reload.done_ratio
320
    Issue.generate!(:estimated_hours => 20, :done_ratio => 50, :parent_issue_id => parent.id)
321
    assert_equal (50 * 20 + 20 * 10) / 30, parent.reload.done_ratio
322
  end
323

  
324
  def test_parent_estimate_should_be_sum_of_leaves
325
    parent = Issue.generate!
326
    Issue.generate!(:estimated_hours => nil, :parent_issue_id => parent.id)
327
    assert_equal nil, parent.reload.estimated_hours
328
    Issue.generate!(:estimated_hours => 5, :parent_issue_id => parent.id)
329
    assert_equal 5, parent.reload.estimated_hours
330
    Issue.generate!(:estimated_hours => 7, :parent_issue_id => parent.id)
331
    assert_equal 12, parent.reload.estimated_hours
332
  end
333

  
334
  def test_move_parent_updates_old_parent_attributes
335
    first_parent = Issue.generate!
336
    second_parent = Issue.generate!
337
    child = Issue.generate!(:estimated_hours => 5, :parent_issue_id => first_parent.id)
338
    assert_equal 5, first_parent.reload.estimated_hours
339
    child.update_attributes(:estimated_hours => 7, :parent_issue_id => second_parent.id)
340
    assert_equal 7, second_parent.reload.estimated_hours
341
    assert_nil first_parent.reload.estimated_hours
342
  end
343

  
344
  def test_reschuling_a_parent_should_reschedule_subtasks
345
    parent = Issue.generate!
346
    c1 = Issue.generate!(:start_date => '2010-05-12', :due_date => '2010-05-18', :parent_issue_id => parent.id)
347
    c2 = Issue.generate!(:start_date => '2010-06-03', :due_date => '2010-06-10', :parent_issue_id => parent.id)
348
    parent.reload
349
    parent.reschedule_on!(Date.parse('2010-06-02'))
350
    c1.reload
351
    assert_equal [Date.parse('2010-06-02'), Date.parse('2010-06-08')], [c1.start_date, c1.due_date]
352
    c2.reload
353
    assert_equal [Date.parse('2010-06-03'), Date.parse('2010-06-10')], [c2.start_date, c2.due_date] # no change
354
    parent.reload
355
    assert_equal [Date.parse('2010-06-02'), Date.parse('2010-06-10')], [parent.start_date, parent.due_date]
356
  end
357

  
358
  def test_project_copy_should_copy_issue_tree
359
    p = Project.create!(:name => 'Tree copy', :identifier => 'tree-copy', :tracker_ids => [1, 2])
360
    i1 = Issue.generate!(:project => p, :subject => 'i1')
361
    i2 = Issue.generate!(:project => p, :subject => 'i2', :parent_issue_id => i1.id)
362
    i3 = Issue.generate!(:project => p, :subject => 'i3', :parent_issue_id => i1.id)
363
    i4 = Issue.generate!(:project => p, :subject => 'i4', :parent_issue_id => i2.id)
364
    i5 = Issue.generate!(:project => p, :subject => 'i5')
365
    c = Project.new(:name => 'Copy', :identifier => 'copy', :tracker_ids => [1, 2])
366
    c.copy(p, :only => 'issues')
367
    c.reload
368

  
369
    assert_equal 5, c.issues.count
370
    ic1, ic2, ic3, ic4, ic5 = c.issues.find(:all, :order => 'subject')
371
    assert ic1.root?
372
    assert_equal ic1, ic2.parent
373
    assert_equal ic1, ic3.parent
374
    assert_equal ic2, ic4.parent
375
    assert ic5.root?
376
  end
377
end

Also available in: Unified diff