##// END OF EJS Templates
Gantt unit tests cleanup....
Jean-Philippe Lang -
r13291:dacae57a3873
parent child
Show More
This diff has been collapsed as it changes many lines, (525 lines changed) Show them Hide them
@@ -1,759 +1,498
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../../../../test_helper', __FILE__)
18 require File.expand_path('../../../../../test_helper', __FILE__)
19
19
20 class Redmine::Helpers::GanttHelperTest < ActionView::TestCase
20 class Redmine::Helpers::GanttHelperTest < ActionView::TestCase
21 fixtures :projects, :trackers, :issue_statuses, :issues,
21 fixtures :trackers, :issue_statuses,
22 :journals, :journal_details,
22 :enumerations, :users, :issue_categories
23 :enumerations, :users, :issue_categories,
24 :projects_trackers,
25 :roles,
26 :member_roles,
27 :members,
28 :enabled_modules,
29 :versions,
30 :groups_users
31
23
32 include ProjectsHelper
24 include ProjectsHelper
33 include IssuesHelper
25 include IssuesHelper
34 include ERB::Util
26 include ERB::Util
35 include Rails.application.routes.url_helpers
27 include Rails.application.routes.url_helpers
36
28
37 def setup
29 def setup
38 setup_with_controller
30 setup_with_controller
39 User.current = User.find(1)
31 User.current = User.find(1)
40 end
32 end
41
33
42 def today
34 def today
43 @today ||= Date.today
35 @today ||= Date.today
44 end
36 end
45 private :today
37 private :today
46
38
39 def gantt_start
40 @gantt.date_from
41 end
42
47 # Creates a Gantt chart for a 4 week span
43 # Creates a Gantt chart for a 4 week span
48 def create_gantt(project=Project.generate!, options={})
44 def create_gantt(project=Project.generate!, options={})
49 @project = project
45 @project = project
50 @gantt = Redmine::Helpers::Gantt.new(options)
46 @gantt = Redmine::Helpers::Gantt.new(options)
51 @gantt.project = @project
47 @gantt.project = @project
52 @gantt.query = IssueQuery.create!(:project => @project, :name => 'Gantt')
48 @gantt.query = IssueQuery.new(:project => @project, :name => 'Gantt')
53 @gantt.view = self
49 @gantt.view = self
54 @gantt.instance_variable_set('@date_from', options[:date_from] || (today - 14))
50 @gantt.instance_variable_set('@date_from', options[:date_from] || (today - 14))
55 @gantt.instance_variable_set('@date_to', options[:date_to] || (today + 14))
51 @gantt.instance_variable_set('@date_to', options[:date_to] || (today + 14))
56 end
52 end
57 private :create_gantt
53 private :create_gantt
58
54
59 test "#number_of_rows with one project should return the number of rows just for that project" do
55 test "#number_of_rows with one project should return the number of rows just for that project" do
60 p1, p2 = Project.generate!, Project.generate!
56 p1, p2 = Project.generate!, Project.generate!
61 i1, i2 = Issue.generate!(:project => p1), Issue.generate!(:project => p2)
57 i1, i2 = Issue.generate!(:project => p1), Issue.generate!(:project => p2)
62 create_gantt(p1)
58 create_gantt(p1)
63 assert_equal 2, @gantt.number_of_rows
59 assert_equal 2, @gantt.number_of_rows
64 end
60 end
65
61
66 test "#number_of_rows with no project should return the total number of rows for all the projects, resursively" do
62 test "#number_of_rows with no project should return the total number of rows for all the projects, resursively" do
67 p1, p2 = Project.generate!, Project.generate!
63 p1, p2 = Project.generate!, Project.generate!
68 create_gantt(nil)
64 create_gantt(nil)
69 # fix the return value of #number_of_rows_on_project() to an arbitrary value
65 # fix the return value of #number_of_rows_on_project() to an arbitrary value
70 # so that we really only test #number_of_rows
66 # so that we really only test #number_of_rows
71 @gantt.stubs(:number_of_rows_on_project).returns(7)
67 @gantt.stubs(:number_of_rows_on_project).returns(7)
72 # also fix #projects because we want to test #number_of_rows in isolation
68 # also fix #projects because we want to test #number_of_rows in isolation
73 @gantt.stubs(:projects).returns(Project.all)
69 @gantt.stubs(:projects).returns(Project.all)
74 # actual test
70 # actual test
75 assert_equal Project.count*7, @gantt.number_of_rows
71 assert_equal Project.count*7, @gantt.number_of_rows
76 end
72 end
77
73
78 test "#number_of_rows should not exceed max_rows option" do
74 test "#number_of_rows should not exceed max_rows option" do
79 p = Project.generate!
75 p = Project.generate!
80 5.times do
76 5.times do
81 Issue.generate!(:project => p)
77 Issue.generate!(:project => p)
82 end
78 end
83 create_gantt(p)
79 create_gantt(p)
84 @gantt.render
80 @gantt.render
85 assert_equal 6, @gantt.number_of_rows
81 assert_equal 6, @gantt.number_of_rows
86 assert !@gantt.truncated
82 assert !@gantt.truncated
87 create_gantt(p, :max_rows => 3)
83 create_gantt(p, :max_rows => 3)
88 @gantt.render
84 @gantt.render
89 assert_equal 3, @gantt.number_of_rows
85 assert_equal 3, @gantt.number_of_rows
90 assert @gantt.truncated
86 assert @gantt.truncated
91 end
87 end
92
88
93 test "#number_of_rows_on_project should count 0 for an empty the project" do
89 test "#number_of_rows_on_project should count 0 for an empty the project" do
94 create_gantt
90 create_gantt
95 assert_equal 0, @gantt.number_of_rows_on_project(@project)
91 assert_equal 0, @gantt.number_of_rows_on_project(@project)
96 end
92 end
97
93
98 test "#number_of_rows_on_project should count the number of issues without a version" do
94 test "#number_of_rows_on_project should count the number of issues without a version" do
99 create_gantt
95 create_gantt
100 @project.issues << Issue.generate!(:project => @project, :fixed_version => nil)
96 @project.issues << Issue.generate!(:project => @project, :fixed_version => nil)
101 assert_equal 2, @gantt.number_of_rows_on_project(@project)
97 assert_equal 2, @gantt.number_of_rows_on_project(@project)
102 end
98 end
103
99
104 test "#number_of_rows_on_project should count the number of issues on versions, including cross-project" do
100 test "#number_of_rows_on_project should count the number of issues on versions, including cross-project" do
105 create_gantt
101 create_gantt
106 version = Version.generate!
102 version = Version.generate!
107 @project.versions << version
103 @project.versions << version
108 @project.issues << Issue.generate!(:project => @project, :fixed_version => version)
104 @project.issues << Issue.generate!(:project => @project, :fixed_version => version)
109 assert_equal 3, @gantt.number_of_rows_on_project(@project)
105 assert_equal 3, @gantt.number_of_rows_on_project(@project)
110 end
106 end
111
107
112 def setup_subjects
108 def setup_subjects
113 create_gantt
109 create_gantt
114 @project.enabled_module_names = [:issue_tracking]
110 @project.enabled_module_names = [:issue_tracking]
115 @tracker = Tracker.generate!
111 @tracker = Tracker.generate!
116 @project.trackers << @tracker
112 @project.trackers << @tracker
117 @version = Version.generate!(:effective_date => (today + 7), :sharing => 'none')
113 @version = Version.generate!(:effective_date => (today + 7), :sharing => 'none')
118 @project.versions << @version
114 @project.versions << @version
119 @issue = Issue.generate!(:fixed_version => @version,
115 @issue = Issue.generate!(:fixed_version => @version,
120 :subject => "gantt#line_for_project",
116 :subject => "gantt#line_for_project",
121 :tracker => @tracker,
117 :tracker => @tracker,
122 :project => @project,
118 :project => @project,
123 :done_ratio => 30,
119 :done_ratio => 30,
124 :start_date => (today - 1),
120 :start_date => (today - 1),
125 :due_date => (today + 7))
121 :due_date => (today + 7))
126 @project.issues << @issue
122 @project.issues << @issue
127 end
123 end
128 private :setup_subjects
124 private :setup_subjects
129
125
130 # TODO: more of an integration test
126 # TODO: more of an integration test
131 test "#subjects project should be rendered" do
127 test "#subjects project should be rendered" do
132 setup_subjects
128 setup_subjects
133 @output_buffer = @gantt.subjects
129 @output_buffer = @gantt.subjects
134 assert_select "div.project-name a", /#{@project.name}/
130 assert_select "div.project-name a", /#{@project.name}/
135 end
136
137 test "#subjects project should have an indent of 4" do
138 setup_subjects
139 @output_buffer = @gantt.subjects
140 assert_select "div.project-name[style*=left:4px]"
131 assert_select "div.project-name[style*=left:4px]"
141 end
132 end
142
133
143 test "#subjects version should be rendered" do
134 test "#subjects version should be rendered" do
144 setup_subjects
135 setup_subjects
145 @output_buffer = @gantt.subjects
136 @output_buffer = @gantt.subjects
146 assert_select "div.version-name a", /#{@version.name}/
137 assert_select "div.version-name a", /#{@version.name}/
147 end
148
149 test "#subjects version should be indented 24 (one level)" do
150 setup_subjects
151 @output_buffer = @gantt.subjects
152 assert_select "div.version-name[style*=left:24px]"
138 assert_select "div.version-name[style*=left:24px]"
153 end
139 end
154
140
155 test "#subjects version without assigned issues should not be rendered" do
141 test "#subjects version without assigned issues should not be rendered" do
156 setup_subjects
142 setup_subjects
157 @version = Version.generate!(:effective_date => (today + 14),
143 @version = Version.generate!(:effective_date => (today + 14),
158 :sharing => 'none',
144 :sharing => 'none',
159 :name => 'empty_version')
145 :name => 'empty_version')
160 @project.versions << @version
146 @project.versions << @version
161 @output_buffer = @gantt.subjects
147 @output_buffer = @gantt.subjects
162 assert_select "div.version-name a", :text => /#{@version.name}/, :count => 0
148 assert_select "div.version-name a", :text => /#{@version.name}/, :count => 0
163 end
149 end
164
150
165 test "#subjects issue should be rendered" do
151 test "#subjects issue should be rendered" do
166 setup_subjects
152 setup_subjects
167 @output_buffer = @gantt.subjects
153 @output_buffer = @gantt.subjects
168 assert_select "div.issue-subject", /#{@issue.subject}/
154 assert_select "div.issue-subject", /#{@issue.subject}/
169 end
170
171 test "#subjects issue should be indented 44 (two levels)" do
172 setup_subjects
173 @output_buffer = @gantt.subjects
174 assert_select "div.issue-subject[style*=left:44px]"
155 assert_select "div.issue-subject[style*=left:44px]"
175 end
156 end
176
157
177 test "#subjects issue assigned to a shared version of another project should be rendered" do
158 test "#subjects issue assigned to a shared version of another project should be rendered" do
178 setup_subjects
159 setup_subjects
179 p = Project.generate!
160 p = Project.generate!
180 p.enabled_module_names = [:issue_tracking]
161 p.enabled_module_names = [:issue_tracking]
181 @shared_version = Version.generate!(:sharing => 'system')
162 @shared_version = Version.generate!(:sharing => 'system')
182 p.versions << @shared_version
163 p.versions << @shared_version
183 # Reassign the issue to a shared version of another project
164 # Reassign the issue to a shared version of another project
184 @issue = Issue.generate!(:fixed_version => @shared_version,
165 @issue = Issue.generate!(:fixed_version => @shared_version,
185 :subject => "gantt#assigned_to_shared_version",
166 :subject => "gantt#assigned_to_shared_version",
186 :tracker => @tracker,
167 :tracker => @tracker,
187 :project => @project,
168 :project => @project,
188 :done_ratio => 30,
169 :done_ratio => 30,
189 :start_date => (today - 1),
170 :start_date => (today - 1),
190 :due_date => (today + 7))
171 :due_date => (today + 7))
191 @project.issues << @issue
172 @project.issues << @issue
192 @output_buffer = @gantt.subjects
173 @output_buffer = @gantt.subjects
193 assert_select "div.issue-subject", /#{@issue.subject}/
174 assert_select "div.issue-subject", /#{@issue.subject}/
194 end
175 end
195
176
196 test "#subjects issue with subtasks should indent subtasks" do
177 test "#subjects issue with subtasks should indent subtasks" do
197 setup_subjects
178 setup_subjects
198 attrs = {:project => @project, :tracker => @tracker, :fixed_version => @version}
179 attrs = {:project => @project, :tracker => @tracker, :fixed_version => @version}
199 @child1 = Issue.generate!(
180 @child1 = Issue.generate!(
200 attrs.merge(:subject => 'child1',
181 attrs.merge(:subject => 'child1',
201 :parent_issue_id => @issue.id,
182 :parent_issue_id => @issue.id,
202 :start_date => (today - 1),
183 :start_date => (today - 1),
203 :due_date => (today + 2))
184 :due_date => (today + 2))
204 )
185 )
205 @child2 = Issue.generate!(
186 @child2 = Issue.generate!(
206 attrs.merge(:subject => 'child2',
187 attrs.merge(:subject => 'child2',
207 :parent_issue_id => @issue.id,
188 :parent_issue_id => @issue.id,
208 :start_date => today,
189 :start_date => today,
209 :due_date => (today + 7))
190 :due_date => (today + 7))
210 )
191 )
211 @grandchild = Issue.generate!(
192 @grandchild = Issue.generate!(
212 attrs.merge(:subject => 'grandchild',
193 attrs.merge(:subject => 'grandchild',
213 :parent_issue_id => @child1.id,
194 :parent_issue_id => @child1.id,
214 :start_date => (today - 1),
195 :start_date => (today - 1),
215 :due_date => (today + 2))
196 :due_date => (today + 2))
216 )
197 )
217 @output_buffer = @gantt.subjects
198 @output_buffer = @gantt.subjects
218 # parent task 44px
199 # parent task 44px
219 assert_select "div.issue-subject[style*=left:44px]", /#{@issue.subject}/
200 assert_select "div.issue-subject[style*=left:44px]", /#{@issue.subject}/
220 # children 64px
201 # children 64px
221 assert_select "div.issue-subject[style*=left:64px]", /child1/
202 assert_select "div.issue-subject[style*=left:64px]", /child1/
222 assert_select "div.issue-subject[style*=left:64px]", /child2/
203 assert_select "div.issue-subject[style*=left:64px]", /child2/
223 # grandchild 84px
204 # grandchild 84px
224 assert_select "div.issue-subject[style*=left:84px]", /grandchild/, @output_buffer
205 assert_select "div.issue-subject[style*=left:84px]", /grandchild/, @output_buffer
225 end
206 end
226
207
227 context "#lines" do
208 test "#lines" do
228 setup do
229 create_gantt
209 create_gantt
230 @project.enabled_module_names = [:issue_tracking]
210 @project.enabled_module_names = [:issue_tracking]
231 @tracker = Tracker.generate!
211 @tracker = Tracker.generate!
232 @project.trackers << @tracker
212 @project.trackers << @tracker
233 @version = Version.generate!(:effective_date => (today + 7))
213 @version = Version.generate!(:effective_date => (today + 7))
234 @project.versions << @version
214 @project.versions << @version
235 @issue = Issue.generate!(:fixed_version => @version,
215 @issue = Issue.generate!(:fixed_version => @version,
236 :subject => "gantt#line_for_project",
216 :subject => "gantt#line_for_project",
237 :tracker => @tracker,
217 :tracker => @tracker,
238 :project => @project,
218 :project => @project,
239 :done_ratio => 30,
219 :done_ratio => 30,
240 :start_date => (today - 1),
220 :start_date => (today - 1),
241 :due_date => (today + 7))
221 :due_date => (today + 7))
242 @project.issues << @issue
222 @project.issues << @issue
243 @output_buffer = @gantt.lines
223 @output_buffer = @gantt.lines
244 end
245
224
246 context "project" do
247 should "be rendered" do
248 assert_select "div.project.task_todo"
225 assert_select "div.project.task_todo"
249 assert_select "div.project.starting"
226 assert_select "div.project.starting"
250 assert_select "div.project.ending"
227 assert_select "div.project.ending"
251 assert_select "div.label.project", /#{@project.name}/
228 assert_select "div.label.project", /#{@project.name}/
252 end
253 end
254
229
255 context "version" do
256 should "be rendered" do
257 assert_select "div.version.task_todo"
230 assert_select "div.version.task_todo"
258 assert_select "div.version.starting"
231 assert_select "div.version.starting"
259 assert_select "div.version.ending"
232 assert_select "div.version.ending"
260 assert_select "div.label.version", /#{@version.name}/
233 assert_select "div.label.version", /#{@version.name}/
261 end
262 end
263
234
264 context "issue" do
265 should "be rendered" do
266 assert_select "div.task_todo"
235 assert_select "div.task_todo"
267 assert_select "div.task.label", /#{@issue.done_ratio}/
236 assert_select "div.task.label", /#{@issue.done_ratio}/
268 assert_select "div.tooltip", /#{@issue.subject}/
237 assert_select "div.tooltip", /#{@issue.subject}/
269 end
238 end
270 end
271 end
272
239
273 context "#subject_for_project" do
240 test "#subject_for_project" do
274 setup do
275 create_gantt
241 create_gantt
276 end
242 @output_buffer = @gantt.subject_for_project(@project, :format => :html)
277
278 context ":html format" do
279 should "add an absolute positioned div" do
280 @output_buffer = @gantt.subject_for_project(@project, {:format => :html})
281 assert_select "div[style*=absolute]"
282 end
283
284 should "use the indent option to move the div to the right" do
285 @output_buffer = @gantt.subject_for_project(@project, {:format => :html, :indent => 40})
286 assert_select "div[style*=left:40]"
287 end
288
289 should "include the project name" do
290 @output_buffer = @gantt.subject_for_project(@project, {:format => :html})
291 assert_select 'div', :text => /#{@project.name}/
292 end
293
294 should "include a link to the project" do
295 @output_buffer = @gantt.subject_for_project(@project, {:format => :html})
296 assert_select 'a[href=?]', "/projects/#{@project.identifier}", :text => /#{@project.name}/
243 assert_select 'a[href=?]', "/projects/#{@project.identifier}", :text => /#{@project.name}/
297 end
244 end
298
245
299 should "style overdue projects" do
246 test "#subject_for_project should style overdue projects" do
300 @project.enabled_module_names = [:issue_tracking]
247 create_gantt
301 @project.versions << Version.generate!(:effective_date => (today - 1))
248 @project.stubs(:overdue?).returns(true)
302 assert @project.reload.overdue?, "Need an overdue project for this test"
249 @output_buffer = @gantt.subject_for_project(@project, :format => :html)
303 @output_buffer = @gantt.subject_for_project(@project, {:format => :html})
304 assert_select 'div span.project-overdue'
250 assert_select 'div span.project-overdue'
305 end
251 end
306 end
307 end
308
252
309 context "#line_for_project" do
253 test "#subject_for_version" do
310 setup do
311 create_gantt
254 create_gantt
312 @project.enabled_module_names = [:issue_tracking]
255 version = Version.generate!(:name => 'Foo', :effective_date => today, :project => @project)
313 @tracker = Tracker.generate!
256 @output_buffer = @gantt.subject_for_version(version, :format => :html)
314 @project.trackers << @tracker
257 assert_select 'a[href=?]', "/versions/#{version.to_param}", :text => /Foo/
315 @version = Version.generate!(:effective_date => (today - 1))
316 @project.versions << @version
317 @project.issues << Issue.generate!(:fixed_version => @version,
318 :subject => "gantt#line_for_project",
319 :tracker => @tracker,
320 :project => @project,
321 :done_ratio => 30,
322 :start_date => (today - 7),
323 :due_date => (today + 7))
324 end
258 end
325
259
326 context ":html format" do
260 test "#subject_for_version should style overdue versions" do
327 context "todo line" do
328 should "start from the starting point on the left" do
329 @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
330 assert_select "div.project.task_todo[style*=left:28px]", true, @output_buffer
331 end
332
333 should "be the total width of the project" do
334 @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
335 assert_select "div.project.task_todo[style*=width:58px]", true, @output_buffer
336 end
337 end
338
339 context "starting marker" do
340 should "not appear if the starting point is off the gantt chart" do
341 # Shift the date range of the chart
342 @gantt.instance_variable_set('@date_from', today)
343 @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
344 assert_select "div.project.starting", false, @output_buffer
345 end
346
347 should "appear at the starting point" do
348 @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
349 assert_select "div.project.starting[style*=left:28px]", true, @output_buffer
350 end
351 end
352
353 context "ending marker" do
354 should "not appear if the starting point is off the gantt chart" do
355 # Shift the date range of the chart
356 @gantt.instance_variable_set('@date_to', (today - 14))
357 @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
358 assert_select "div.project.ending", false, @output_buffer
359 end
360
361 should "appear at the end of the date range" do
362 @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
363 assert_select "div.project.ending[style*=left:88px]", true, @output_buffer
364 end
365 end
366
367 context "status content" do
368 should "appear at the far left, even if it's far in the past" do
369 @gantt.instance_variable_set('@date_to', (today - 14))
370 @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
371 assert_select "div.project.label", /#{@project.name}/
372 end
373
374 should "show the project name" do
375 @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
376 assert_select "div.project.label", /#{@project.name}/
377 end
378 end
379 end
380 end
381
382 context "#subject_for_version" do
383 setup do
384 create_gantt
261 create_gantt
385 @project.enabled_module_names = [:issue_tracking]
262 version = Version.generate!(:name => 'Foo', :effective_date => today, :project => @project)
386 @tracker = Tracker.generate!
263 version.stubs(:overdue?).returns(true)
387 @project.trackers << @tracker
264 @output_buffer = @gantt.subject_for_version(version, :format => :html)
388 @version = Version.generate!(:effective_date => (today - 1))
265 assert_select 'div span.version-overdue'
389 @project.versions << @version
390 @project.issues << Issue.generate!(:fixed_version => @version,
391 :subject => "gantt#subject_for_version",
392 :tracker => @tracker,
393 :project => @project,
394 :start_date => today)
395
396 end
397
398 context ":html format" do
399 should "add an absolute positioned div" do
400 @output_buffer = @gantt.subject_for_version(@version, {:format => :html})
401 assert_select "div[style*=absolute]"
402 end
403
404 should "use the indent option to move the div to the right" do
405 @output_buffer = @gantt.subject_for_version(@version, {:format => :html, :indent => 40})
406 assert_select "div[style*=left:40]"
407 end
408
409 should "include the version name" do
410 @output_buffer = @gantt.subject_for_version(@version, {:format => :html})
411 assert_select 'div', :text => /#{@version.name}/
412 end
413
414 should "include a link to the version" do
415 @output_buffer = @gantt.subject_for_version(@version, {:format => :html})
416 assert_select 'a[href=?]', Regexp.escape("/versions/#{@version.to_param}"), :text => /#{@version.name}/
417 end
266 end
418
267
419 should "style late versions" do
268 test "#subject_for_version should style behind schedule versions" do
420 assert @version.overdue?, "Need an overdue version for this test"
269 create_gantt
421 @output_buffer = @gantt.subject_for_version(@version, {:format => :html})
270 version = Version.generate!(:name => 'Foo', :effective_date => today, :project => @project)
271 version.stubs(:behind_schedule?).returns(true)
272 @output_buffer = @gantt.subject_for_version(version, :format => :html)
422 assert_select 'div span.version-behind-schedule'
273 assert_select 'div span.version-behind-schedule'
423 end
274 end
424
275
425 should "style behind schedule versions" do
276 test "#subject_for_issue" do
426 assert @version.behind_schedule?, "Need a behind schedule version for this test"
427 @output_buffer = @gantt.subject_for_version(@version, {:format => :html})
428 assert_select 'div span.version-behind-schedule'
429 end
430 end
431 end
432
433 context "#line_for_version" do
434 setup do
435 create_gantt
277 create_gantt
436 @project.enabled_module_names = [:issue_tracking]
278 issue = Issue.generate!(:project => @project)
437 @tracker = Tracker.generate!
279 @output_buffer = @gantt.subject_for_issue(issue, :format => :html)
438 @project.trackers << @tracker
280 assert_select 'div', :text => /#{issue.subject}/
439 @version = Version.generate!(:effective_date => (today + 7))
281 assert_select 'a[href=?]', "/issues/#{issue.to_param}", :text => /#{issue.tracker.name} ##{issue.id}/
440 @project.versions << @version
441 @project.issues << Issue.generate!(:fixed_version => @version,
442 :subject => "gantt#line_for_project",
443 :tracker => @tracker,
444 :project => @project,
445 :done_ratio => 30,
446 :start_date => (today - 7),
447 :due_date => (today + 7))
448 end
449
450 context ":html format" do
451 context "todo line" do
452 should "start from the starting point on the left" do
453 @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
454 assert_select "div.version.task_todo[style*=left:28px]", true, @output_buffer
455 end
456
457 should "be the total width of the version" do
458 @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
459 assert_select "div.version.task_todo[style*=width:58px]", true, @output_buffer
460 end
461 end
462
463 context "late line" do
464 should "start from the starting point on the left" do
465 @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
466 assert_select "div.version.task_late[style*=left:28px]", true, @output_buffer
467 end
468
469 should "be the total delayed width of the version" do
470 @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
471 assert_select "div.version.task_late[style*=width:30px]", true, @output_buffer
472 end
473 end
474
475 context "done line" do
476 should "start from the starting point on the left" do
477 @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
478 assert_select "div.version.task_done[style*=left:28px]", true, @output_buffer
479 end
480
481 should "be the total done width of the version" do
482 @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
483 assert_select "div.version.task_done[style*=width:16px]", true, @output_buffer
484 end
485 end
486
487 context "starting marker" do
488 should "not appear if the starting point is off the gantt chart" do
489 # Shift the date range of the chart
490 @gantt.instance_variable_set('@date_from', today)
491 @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
492 assert_select "div.version.starting", false
493 end
282 end
494
283
495 should "appear at the starting point" do
284 test "#subject_for_issue should style overdue issues" do
496 @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
497 assert_select "div.version.starting[style*=left:28px]", true, @output_buffer
498 end
499 end
500
501 context "ending marker" do
502 should "not appear if the starting point is off the gantt chart" do
503 # Shift the date range of the chart
504 @gantt.instance_variable_set('@date_to', (today - 14))
505 @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
506 assert_select "div.version.ending", false
507 end
508
509 should "appear at the end of the date range" do
510 @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
511 assert_select "div.version.ending[style*=left:88px]", true, @output_buffer
512 end
513 end
514
515 context "status content" do
516 should "appear at the far left, even if it's far in the past" do
517 @gantt.instance_variable_set('@date_to', (today - 14))
518 @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
519 assert_select "div.version.label", /#{@version.name}/
520 end
521
522 should "show the version name" do
523 @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
524 assert_select "div.version.label", /#{@version.name}/
525 end
526
527 should "show the percent complete" do
528 @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
529 assert_select "div.version.label", /30%/
530 end
531 end
532 end
533 end
534
535 context "#subject_for_issue" do
536 setup do
537 create_gantt
285 create_gantt
538 @project.enabled_module_names = [:issue_tracking]
286 issue = Issue.generate!(:project => @project)
539 @tracker = Tracker.generate!
287 issue.stubs(:overdue?).returns(true)
540 @project.trackers << @tracker
288 @output_buffer = @gantt.subject_for_issue(issue, :format => :html)
541 @issue = Issue.generate!(:subject => "gantt#subject_for_issue",
289 assert_select 'div span.issue-overdue'
542 :tracker => @tracker,
543 :project => @project,
544 :start_date => (today - 3),
545 :due_date => (today - 1))
546 @project.issues << @issue
547 end
290 end
548
291
549 context ":html format" do
292 test "#subject should add an absolute positioned div" do
550 should "add an absolute positioned div" do
293 create_gantt
551 @output_buffer = @gantt.subject_for_issue(@issue, {:format => :html})
294 @output_buffer = @gantt.subject('subject', :format => :html)
552 assert_select "div[style*=absolute]"
295 assert_select "div[style*=absolute]", :text => 'subject'
553 end
296 end
554
297
555 should "use the indent option to move the div to the right" do
298 test "#subject should use the indent option to move the div to the right" do
556 @output_buffer = @gantt.subject_for_issue(@issue, {:format => :html, :indent => 40})
299 create_gantt
300 @output_buffer = @gantt.subject('subject', :format => :html, :indent => 40)
557 assert_select "div[style*=left:40]"
301 assert_select "div[style*=left:40]"
558 end
302 end
559
303
560 should "include the issue subject" do
304 test "#line_for_project" do
561 @output_buffer = @gantt.subject_for_issue(@issue, {:format => :html})
305 create_gantt
562 assert_select 'div', :text => /#{@issue.subject}/
306 @project.stubs(:start_date).returns(today - 7)
563 end
307 @project.stubs(:due_date).returns(today + 7)
564
308 @output_buffer = @gantt.line_for_project(@project, :format => :html)
565 should "include a link to the issue" do
309 assert_select "div.project.label", :text => @project.name
566 @output_buffer = @gantt.subject_for_issue(@issue, {:format => :html})
567 assert_select 'a[href=?]', Regexp.escape("/issues/#{@issue.to_param}"), :text => /#{@tracker.name} ##{@issue.id}/
568 end
310 end
569
311
570 should "style overdue issues" do
312 test "#line_for_version" do
571 assert @issue.overdue?, "Need an overdue issue for this test"
313 create_gantt
572 @output_buffer = @gantt.subject_for_issue(@issue, {:format => :html})
314 version = Version.generate!(:name => 'Foo', :project => @project)
573 assert_select 'div span.issue-overdue'
315 version.stubs(:start_date).returns(today - 7)
574 end
316 version.stubs(:due_date).returns(today + 7)
575 end
317 version.stubs(:completed_percent).returns(30)
318 @output_buffer = @gantt.line_for_version(version, :format => :html)
319 assert_select "div.version.label", :text => /Foo/
320 assert_select "div.version.label", :text => /30%/
576 end
321 end
577
322
578 context "#line_for_issue" do
323 test "#line_for_issue" do
579 setup do
580 create_gantt
324 create_gantt
581 @project.enabled_module_names = [:issue_tracking]
325 issue = Issue.generate!(:project => @project, :start_date => today - 7, :due_date => today + 7, :done_ratio => 30)
582 @tracker = Tracker.generate!
326 @output_buffer = @gantt.line_for_issue(issue, :format => :html)
583 @project.trackers << @tracker
327 assert_select "div.task.label", :text => /#{issue.status.name}/
584 @version = Version.generate!(:effective_date => (today + 7))
328 assert_select "div.task.label", :text => /30%/
585 @project.versions << @version
329 assert_select "div.tooltip", /#{issue.subject}/
586 @issue = Issue.generate!(:fixed_version => @version,
587 :subject => "gantt#line_for_project",
588 :tracker => @tracker,
589 :project => @project,
590 :done_ratio => 30,
591 :start_date => (today - 7),
592 :due_date => (today + 7))
593 @project.issues << @issue
594 end
330 end
595
331
596 context ":html format" do
332 test "#line todo line should start from the starting point on the left" do
597 context "todo line" do
333 create_gantt
598 should "start from the starting point on the left" do
334 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
599 @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
335 assert_select "div.task_todo[style*=left:28px]", 1
600 assert_select "div.task_todo[style*=left:28px]", true, @output_buffer
601 end
336 end
602
337
603 should "be the total width of the issue" do
338 test "#line todo line should be the total width" do
604 @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
339 create_gantt
605 assert_select "div.task_todo[style*=width:58px]", true, @output_buffer
340 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
606 end
341 assert_select "div.task_todo[style*=width:58px]", 1
607 end
342 end
608
343
609 context "late line" do
344 test "#line late line should start from the starting point on the left" do
610 should "start from the starting point on the left" do
345 create_gantt
611 @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
346 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
612 assert_select "div.task_late[style*=left:28px]", true, @output_buffer
347 assert_select "div.task_late[style*=left:28px]", 1
613 end
348 end
614
349
615 should "be the total delayed width of the issue" do
350 test "#line late line should be the total delayed width" do
616 @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
351 create_gantt
617 assert_select "div.task_late[style*=width:30px]", true, @output_buffer
352 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
618 end
353 assert_select "div.task_late[style*=width:30px]", 1
619 end
354 end
620
355
621 context "done line" do
356 test "#line done line should start from the starting point on the left" do
622 should "start from the starting point on the left" do
357 create_gantt
623 @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
358 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
624 assert_select "div.task_done[style*=left:28px]", true, @output_buffer
359 assert_select "div.task_done[style*=left:28px]", 1
625 end
360 end
626
361
627 should "be the total done width of the issue" do
362 test "#line done line should be the width for the done ratio" do
628 @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
363 create_gantt
364 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
629 # 15 days * 4 px * 30% - 2 px for borders = 16 px
365 # 15 days * 4 px * 30% - 2 px for borders = 16 px
630 assert_select "div.task_done[style*=width:16px]", true, @output_buffer
366 assert_select "div.task_done[style*=width:16px]", 1
631 end
367 end
632
368
633 should "not be the total done width if the chart starts after issue start date" do
369 test "#line done line should be the total width for 100% done ratio" do
634 create_gantt(@project, :date_from => (today - 5))
370 create_gantt
635 @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
371 @output_buffer = @gantt.line(today - 7, today + 7, 100, false, 'line', :format => :html, :zoom => 4)
636 assert_select "div.task_done[style*=left:0px]", true, @output_buffer
372 # 15 days * 4 px - 2 px for borders = 58 px
637 assert_select "div.task_done[style*=width:8px]", true, @output_buffer
373 assert_select "div.task_done[style*=width:58px]", 1
638 end
374 end
639
375
640 context "for completed issue" do
376 test "#line done line should be the total width for 100% done ratio with same start and end dates" do
641 setup do
377 create_gantt
642 @issue.done_ratio = 100
378 @output_buffer = @gantt.line(today + 7, today + 7, 100, false, 'line', :format => :html, :zoom => 4)
379 assert_select "div.task_done[style*=width:2px]", 1
643 end
380 end
644
381
645 should "be the total width of the issue" do
382 test "#line done line should not be the total done width if the gantt starts after start date" do
646 @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
383 create_gantt
647 assert_select "div.task_done[style*=width:58px]", true, @output_buffer
384 @output_buffer = @gantt.line(today - 16, today - 2, 30, false, 'line', :format => :html, :zoom => 4)
385 assert_select "div.task_done[style*=left:0px]", 1
386 assert_select "div.task_done[style*=width:8px]", 1
648 end
387 end
649
388
650 should "be the total width of the issue with due_date=start_date" do
389 test "#line starting marker should appear at the start date" do
651 @issue.due_date = @issue.start_date
390 create_gantt
652 @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
391 @output_buffer = @gantt.line(today - 7, today + 7, 30, true, 'line', :format => :html, :zoom => 4)
653 assert_select "div.task_done[style*=width:2px]", true, @output_buffer
392 assert_select "div.starting", 1
654 end
393 assert_select "div.starting[style*=left:28px]", 1
655 end
656 end
394 end
657
395
658 context "status content" do
396 test "#line starting marker should not appear if the start date is before gantt start date" do
659 should "appear at the far left, even if it's far in the past" do
397 create_gantt
660 @gantt.instance_variable_set('@date_to', (today - 14))
398 @output_buffer = @gantt.line(gantt_start - 2, today + 7, 30, true, 'line', :format => :html, :zoom => 4)
661 @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
399 assert_select "div.starting", 0
662 assert_select "div.task.label", true, @output_buffer
663 end
400 end
664
401
665 should "show the issue status" do
402 test "#line ending marker should appear at the end date" do
666 @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
403 create_gantt
667 assert_select "div.task.label", /#{@issue.status.name}/
404 @output_buffer = @gantt.line(today - 7, today + 7, 30, true, 'line', :format => :html, :zoom => 4)
405 assert_select "div.ending", 1
406 assert_select "div.ending[style*=left:88px]", 1
668 end
407 end
669
408
670 should "show the percent complete" do
409 test "#line ending marker should not appear if the end date is before gantt start date" do
671 @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
410 create_gantt
672 assert_select "div.task.label", /30%/
411 @output_buffer = @gantt.line(gantt_start - 30, gantt_start - 21, 30, true, 'line', :format => :html)
673 end
412 assert_select "div.ending", 0
674 end
675 end
413 end
676
414
677 should "have an issue tooltip" do
415 test "#line label should appear at the far left, even if it's before gantt start date" do
678 @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
416 create_gantt
679 assert_select "div.tooltip", /#{@issue.subject}/
417 @output_buffer = @gantt.line(gantt_start - 30, gantt_start - 21, 30, true, 'line', :format => :html)
680 end
418 assert_select "div.label", :text => 'line'
681 end
419 end
682
420
683 def test_sort_issues_no_date
421 def test_sort_issues_no_date
684 project = Project.generate!
422 project = Project.generate!
685 issue1 = Issue.generate!(:subject => "test", :project => project)
423 issue1 = Issue.generate!(:subject => "test", :project => project)
686 issue2 = Issue.generate!(:subject => "test", :project => project)
424 issue2 = Issue.generate!(:subject => "test", :project => project)
687 assert issue1.root_id < issue2.root_id
425 assert issue1.root_id < issue2.root_id
688 child1 = Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
426 child1 = Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
689 :project => project)
427 :project => project)
690 child2 = Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
428 child2 = Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
691 :project => project)
429 :project => project)
692 child3 = Issue.generate!(:parent_issue_id => child1.id, :subject => 'child',
430 child3 = Issue.generate!(:parent_issue_id => child1.id, :subject => 'child',
693 :project => project)
431 :project => project)
694 assert_equal child1.root_id, child2.root_id
432 assert_equal child1.root_id, child2.root_id
695 assert child1.lft < child2.lft
433 assert child1.lft < child2.lft
696 assert child3.lft < child2.lft
434 assert child3.lft < child2.lft
697 issues = [child3, child2, child1, issue2, issue1]
435 issues = [child3, child2, child1, issue2, issue1]
698 Redmine::Helpers::Gantt.sort_issues!(issues)
436 Redmine::Helpers::Gantt.sort_issues!(issues)
699 assert_equal [issue1.id, child1.id, child3.id, child2.id, issue2.id],
437 assert_equal [issue1.id, child1.id, child3.id, child2.id, issue2.id],
700 issues.map{|v| v.id}
438 issues.map{|v| v.id}
701 end
439 end
702
440
703 def test_sort_issues_root_only
441 def test_sort_issues_root_only
704 project = Project.generate!
442 project = Project.generate!
705 issue1 = Issue.generate!(:subject => "test", :project => project)
443 issue1 = Issue.generate!(:subject => "test", :project => project)
706 issue2 = Issue.generate!(:subject => "test", :project => project)
444 issue2 = Issue.generate!(:subject => "test", :project => project)
707 issue3 = Issue.generate!(:subject => "test", :project => project,
445 issue3 = Issue.generate!(:subject => "test", :project => project,
708 :start_date => (today - 1))
446 :start_date => (today - 1))
709 issue4 = Issue.generate!(:subject => "test", :project => project,
447 issue4 = Issue.generate!(:subject => "test", :project => project,
710 :start_date => (today - 2))
448 :start_date => (today - 2))
711 issues = [issue4, issue3, issue2, issue1]
449 issues = [issue4, issue3, issue2, issue1]
712 Redmine::Helpers::Gantt.sort_issues!(issues)
450 Redmine::Helpers::Gantt.sort_issues!(issues)
713 assert_equal [issue1.id, issue2.id, issue4.id, issue3.id],
451 assert_equal [issue1.id, issue2.id, issue4.id, issue3.id],
714 issues.map{|v| v.id}
452 issues.map{|v| v.id}
715 end
453 end
716
454
717 def test_sort_issues_tree
455 def test_sort_issues_tree
718 project = Project.generate!
456 project = Project.generate!
719 issue1 = Issue.generate!(:subject => "test", :project => project)
457 issue1 = Issue.generate!(:subject => "test", :project => project)
720 issue2 = Issue.generate!(:subject => "test", :project => project,
458 issue2 = Issue.generate!(:subject => "test", :project => project,
721 :start_date => (today - 2))
459 :start_date => (today - 2))
722 issue1_child1 =
460 issue1_child1 =
723 Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
461 Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
724 :project => project)
462 :project => project)
725 issue1_child2 =
463 issue1_child2 =
726 Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
464 Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
727 :project => project, :start_date => (today - 10))
465 :project => project, :start_date => (today - 10))
728 issue1_child1_child1 =
466 issue1_child1_child1 =
729 Issue.generate!(:parent_issue_id => issue1_child1.id, :subject => 'child',
467 Issue.generate!(:parent_issue_id => issue1_child1.id, :subject => 'child',
730 :project => project, :start_date => (today - 8))
468 :project => project, :start_date => (today - 8))
731 issue1_child1_child2 =
469 issue1_child1_child2 =
732 Issue.generate!(:parent_issue_id => issue1_child1.id, :subject => 'child',
470 Issue.generate!(:parent_issue_id => issue1_child1.id, :subject => 'child',
733 :project => project, :start_date => (today - 9))
471 :project => project, :start_date => (today - 9))
734 issue1_child1_child1_logic = Redmine::Helpers::Gantt.sort_issue_logic(issue1_child1_child1)
472 issue1_child1_child1_logic = Redmine::Helpers::Gantt.sort_issue_logic(issue1_child1_child1)
735 assert_equal [[today - 10, issue1.id], [today - 9, issue1_child1.id],
473 assert_equal [[today - 10, issue1.id], [today - 9, issue1_child1.id],
736 [today - 8, issue1_child1_child1.id]],
474 [today - 8, issue1_child1_child1.id]],
737 issue1_child1_child1_logic
475 issue1_child1_child1_logic
738 issue1_child1_child2_logic = Redmine::Helpers::Gantt.sort_issue_logic(issue1_child1_child2)
476 issue1_child1_child2_logic = Redmine::Helpers::Gantt.sort_issue_logic(issue1_child1_child2)
739 assert_equal [[today - 10, issue1.id], [today - 9, issue1_child1.id],
477 assert_equal [[today - 10, issue1.id], [today - 9, issue1_child1.id],
740 [today - 9, issue1_child1_child2.id]],
478 [today - 9, issue1_child1_child2.id]],
741 issue1_child1_child2_logic
479 issue1_child1_child2_logic
742 issues = [issue1_child1_child2, issue1_child1_child1, issue1_child2,
480 issues = [issue1_child1_child2, issue1_child1_child1, issue1_child2,
743 issue1_child1, issue2, issue1]
481 issue1_child1, issue2, issue1]
744 Redmine::Helpers::Gantt.sort_issues!(issues)
482 Redmine::Helpers::Gantt.sort_issues!(issues)
745 assert_equal [issue1.id, issue1_child1.id, issue1_child2.id,
483 assert_equal [issue1.id, issue1_child1.id, issue1_child2.id,
746 issue1_child1_child2.id, issue1_child1_child1.id, issue2.id],
484 issue1_child1_child2.id, issue1_child1_child1.id, issue2.id],
747 issues.map{|v| v.id}
485 issues.map{|v| v.id}
748 end
486 end
749
487
750 def test_sort_versions
488 def test_sort_versions
751 project = Project.generate!
489 project = Project.generate!
752 version1 = Version.create!(:project => project, :name => 'test1')
490 versions = []
753 version2 = Version.create!(:project => project, :name => 'test2', :effective_date => '2013-10-25')
491 versions << Version.create!(:project => project, :name => 'test1')
754 version3 = Version.create!(:project => project, :name => 'test3')
492 versions << Version.create!(:project => project, :name => 'test2', :effective_date => '2013-10-25')
755 version4 = Version.create!(:project => project, :name => 'test4', :effective_date => '2013-10-02')
493 versions << Version.create!(:project => project, :name => 'test3')
494 versions << Version.create!(:project => project, :name => 'test4', :effective_date => '2013-10-02')
756
495
757 assert_equal versions.sort, Redmine::Helpers::Gantt.sort_versions!(versions)
496 assert_equal versions.sort, Redmine::Helpers::Gantt.sort_versions!(versions.dup)
758 end
497 end
759 end
498 end
General Comments 0
You need to be logged in to leave comments. Login now