#-- encoding: UTF-8 #-- copyright # ChiliProject is a project management system. # # Copyright (C) 2010-2013 the ChiliProject Team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # See doc/COPYRIGHT.rdoc for more details. #++ require File.expand_path('../../../../../test_helper', __FILE__) class Redmine::Helpers::GanttTest < ActiveSupport::TestCase # Utility methods and classes so assert_select can be used. class GanttViewTest < ActionView::Base include ActionView::Helpers::UrlHelper include ActionView::Helpers::TextHelper include ActionController::UrlWriter include ApplicationHelper include ProjectsHelper include IssuesHelper def self.default_url_options {:only_path => true } end end include ActionController::Assertions::SelectorAssertions def setup @response = ActionController::TestResponse.new # Fixtures ProjectCustomField.delete_all Project.destroy_all User.current = User.find(1) end def build_view @view = GanttViewTest.new end def html_document HTML::Document.new(@response.body) end # Creates a Gantt chart for a 4 week span def create_gantt(project=Project.generate!, options={}) @project = project @gantt = Redmine::Helpers::Gantt.new(options) @gantt.project = @project @gantt.query = Query.generate_default!(:project => @project) @gantt.view = build_view @gantt.instance_variable_set('@date_from', options[:date_from] || 2.weeks.ago.to_date) @gantt.instance_variable_set('@date_to', options[:date_to] || 2.weeks.from_now.to_date) end context "#number_of_rows" do context "with one project" do should "return the number of rows just for that project" end context "with no project" do should "return the total number of rows for all the projects, resursively" end should "not exceed max_rows option" do p = Project.generate! 5.times do Issue.generate_for_project!(p) end create_gantt(p) @gantt.render assert_equal 6, @gantt.number_of_rows assert !@gantt.truncated create_gantt(p, :max_rows => 3) @gantt.render assert_equal 3, @gantt.number_of_rows assert @gantt.truncated end end context "#number_of_rows_on_project" do setup do create_gantt end should "count 0 for an empty the project" do assert_equal 0, @gantt.number_of_rows_on_project(@project) end should "count the number of issues without a version" do @project.issues << Issue.generate_for_project!(@project, :fixed_version => nil) assert_equal 2, @gantt.number_of_rows_on_project(@project) end should "count the number of issues on versions, including cross-project" do version = Version.generate! @project.versions << version @project.issues << Issue.generate_for_project!(@project, :fixed_version => version) assert_equal 3, @gantt.number_of_rows_on_project(@project) end end # TODO: more of an integration test context "#subjects" do setup do create_gantt @project.enabled_module_names = [:issue_tracking] @tracker = Tracker.generate! @project.trackers << @tracker @version = Version.generate!(:effective_date => 1.week.from_now.to_date, :sharing => 'none') @project.versions << @version @issue = Issue.generate!(:fixed_version => @version, :subject => "gantt#line_for_project", :tracker => @tracker, :project => @project, :done_ratio => 30, :start_date => Date.yesterday, :due_date => 1.week.from_now.to_date) @project.issues << @issue end context "project" do should "be rendered" do @response.body = @gantt.subjects assert_select "div.project-name a", /#{@project.name}/ end should "have an indent of 4" do @response.body = @gantt.subjects assert_select "div.project-name[style*=left:4px]" end end context "version" do should "be rendered" do @response.body = @gantt.subjects assert_select "div.version-name a", /#{@version.name}/ end should "be indented 24 (one level)" do @response.body = @gantt.subjects assert_select "div.version-name[style*=left:24px]" end context "without assigned issues" do setup do @version = Version.generate!(:effective_date => 2.week.from_now.to_date, :sharing => 'none', :name => 'empty_version') @project.versions << @version end should "not be rendered" do @response.body = @gantt.subjects assert_select "div.version-name a", :text => /#{@version.name}/, :count => 0 end end end context "issue" do should "be rendered" do @response.body = @gantt.subjects assert_select "div.issue-subject", /#{@issue.subject}/ end should "be indented 44 (two levels)" do @response.body = @gantt.subjects assert_select "div.issue-subject[style*=left:44px]" end context "assigned to a shared version of another project" do setup do p = Project.generate! p.trackers << @tracker p.enabled_module_names = [:issue_tracking] @shared_version = Version.generate!(:sharing => 'system') p.versions << @shared_version # Reassign the issue to a shared version of another project @issue = Issue.generate!(:fixed_version => @shared_version, :subject => "gantt#assigned_to_shared_version", :tracker => @tracker, :project => @project, :done_ratio => 30, :start_date => Date.yesterday, :due_date => 1.week.from_now.to_date) @project.issues << @issue end should "be rendered" do @response.body = @gantt.subjects assert_select "div.issue-subject", /#{@issue.subject}/ end end context "with subtasks" do setup do attrs = {:project => @project, :tracker => @tracker, :fixed_version => @version} @child1 = Issue.generate!(attrs.merge(:subject => 'child1', :parent_issue_id => @issue.id, :start_date => Date.yesterday, :due_date => 2.day.from_now.to_date)) @child2 = Issue.generate!(attrs.merge(:subject => 'child2', :parent_issue_id => @issue.id, :start_date => Date.today, :due_date => 1.week.from_now.to_date)) @grandchild = Issue.generate!(attrs.merge(:subject => 'grandchild', :parent_issue_id => @child1.id, :start_date => Date.yesterday, :due_date => 2.day.from_now.to_date)) end should "indent subtasks" do @response.body = @gantt.subjects # parent task 44px assert_select "div.issue-subject[style*=left:44px]", /#{@issue.subject}/ # children 64px assert_select "div.issue-subject[style*=left:64px]", /child1/ assert_select "div.issue-subject[style*=left:64px]", /child2/ # grandchild 84px assert_select "div.issue-subject[style*=left:84px]", /grandchild/, @response.body end end end end context "#lines" do setup do create_gantt @project.enabled_module_names = [:issue_tracking] @tracker = Tracker.generate! @project.trackers << @tracker @version = Version.generate!(:effective_date => 1.week.from_now.to_date) @project.versions << @version @issue = Issue.generate!(:fixed_version => @version, :subject => "gantt#line_for_project", :tracker => @tracker, :project => @project, :done_ratio => 30, :start_date => Date.yesterday, :due_date => 1.week.from_now.to_date) @project.issues << @issue @response.body = @gantt.lines end context "project" do should "be rendered" do assert_select "div.project.task_todo" assert_select "div.project.starting" assert_select "div.project.ending" assert_select "div.label.project", /#{@project.name}/ end end context "version" do should "be rendered" do assert_select "div.version.task_todo" assert_select "div.version.starting" assert_select "div.version.ending" assert_select "div.label.version", /#{@version.name}/ end end context "issue" do should "be rendered" do assert_select "div.task_todo" assert_select "div.task.label", /#{@issue.done_ratio}/ assert_select "div.tooltip", /#{@issue.subject}/ end end end context "#render_project" do should "be tested" end context "#render_issues" do should "be tested" end context "#render_version" do should "be tested" end context "#subject_for_project" do setup do create_gantt end context ":html format" do should "add an absolute positioned div" do @response.body = @gantt.subject_for_project(@project, {:format => :html}) assert_select "div[style*=absolute]" end should "use the indent option to move the div to the right" do @response.body = @gantt.subject_for_project(@project, {:format => :html, :indent => 40}) assert_select "div[style*=left:40]" end should "include the project name" do @response.body = @gantt.subject_for_project(@project, {:format => :html}) assert_select 'div', :text => /#{@project.name}/ end should "include a link to the project" do @response.body = @gantt.subject_for_project(@project, {:format => :html}) assert_select 'a[href=?]', "/projects/#{@project.identifier}", :text => /#{@project.name}/ end should "style overdue projects" do @project.enabled_module_names = [:issue_tracking] @project.versions << Version.generate!(:effective_date => Date.yesterday) assert @project.overdue?, "Need an overdue project for this test" @response.body = @gantt.subject_for_project(@project, {:format => :html}) assert_select 'div span.project-overdue' end end should "test the PNG format" should "test the PDF format" end context "#line_for_project" do setup do create_gantt @project.enabled_module_names = [:issue_tracking] @tracker = Tracker.generate! @project.trackers << @tracker @version = Version.generate!(:effective_date => Date.yesterday) @project.versions << @version @project.issues << Issue.generate!(:fixed_version => @version, :subject => "gantt#line_for_project", :tracker => @tracker, :project => @project, :done_ratio => 30, :start_date => 1.week.ago.to_date, :due_date => 1.week.from_now.to_date) end context ":html format" do context "todo line" do should "start from the starting point on the left" do @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4}) assert_select "div.project.task_todo[style*=left:28px]", true, @response.body end should "be the total width of the project" do @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4}) assert_select "div.project.task_todo[style*=width:58px]", true, @response.body end end context "late line" do should_eventually "start from the starting point on the left" do @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4}) assert_select "div.project.task_late[style*=left:28px]", true, @response.body end should_eventually "be the total delayed width of the project" do @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4}) assert_select "div.project.task_late[style*=width:30px]", true, @response.body end end context "done line" do should_eventually "start from the starting point on the left" do @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4}) assert_select "div.project.task_done[style*=left:28px]", true, @response.body end should_eventually "Be the total done width of the project" do @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4}) assert_select "div.project.task_done[style*=width:18px]", true, @response.body end end context "starting marker" do should "not appear if the starting point is off the gantt chart" do # Shift the date range of the chart @gantt.instance_variable_set('@date_from', Date.today) @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4}) assert_select "div.project.starting", false, @response.body end should "appear at the starting point" do @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4}) assert_select "div.project.starting[style*=left:28px]", true, @response.body end end context "ending marker" do should "not appear if the starting point is off the gantt chart" do # Shift the date range of the chart @gantt.instance_variable_set('@date_to', 2.weeks.ago.to_date) @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4}) assert_select "div.project.ending", false, @response.body end should "appear at the end of the date range" do @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4}) assert_select "div.project.ending[style*=left:88px]", true, @response.body end end context "status content" do should "appear at the far left, even if it's far in the past" do @gantt.instance_variable_set('@date_to', 2.weeks.ago.to_date) @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4}) assert_select "div.project.label", /#{@project.name}/ end should "show the project name" do @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4}) assert_select "div.project.label", /#{@project.name}/ end should_eventually "show the percent complete" do @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4}) assert_select "div.project.label", /0%/ end end end should "test the PNG format" should "test the PDF format" end context "#subject_for_version" do setup do create_gantt @project.enabled_module_names = [:issue_tracking] @tracker = Tracker.generate! @project.trackers << @tracker @version = Version.generate!(:effective_date => Date.yesterday) @project.versions << @version @project.issues << Issue.generate!(:fixed_version => @version, :subject => "gantt#subject_for_version", :tracker => @tracker, :project => @project, :start_date => Date.today) end context ":html format" do should "add an absolute positioned div" do @response.body = @gantt.subject_for_version(@version, {:format => :html}) assert_select "div[style*=absolute]" end should "use the indent option to move the div to the right" do @response.body = @gantt.subject_for_version(@version, {:format => :html, :indent => 40}) assert_select "div[style*=left:40]" end should "include the version name" do @response.body = @gantt.subject_for_version(@version, {:format => :html}) assert_select 'div', :text => /#{@version.name}/ end should "include a link to the version" do @response.body = @gantt.subject_for_version(@version, {:format => :html}) assert_select 'a[href=?]', Regexp.escape("/versions/show/#{@version.to_param}"), :text => /#{@version.name}/ end should "style late versions" do assert @version.overdue?, "Need an overdue version for this test" @response.body = @gantt.subject_for_version(@version, {:format => :html}) assert_select 'div span.version-behind-schedule' end should "style behind schedule versions" do assert @version.behind_schedule?, "Need a behind schedule version for this test" @response.body = @gantt.subject_for_version(@version, {:format => :html}) assert_select 'div span.version-behind-schedule' end end should "test the PNG format" should "test the PDF format" end context "#line_for_version" do setup do create_gantt @project.enabled_module_names = [:issue_tracking] @tracker = Tracker.generate! @project.trackers << @tracker @version = Version.generate!(:effective_date => 1.week.from_now.to_date) @project.versions << @version @project.issues << Issue.generate!(:fixed_version => @version, :subject => "gantt#line_for_project", :tracker => @tracker, :project => @project, :done_ratio => 30, :start_date => 1.week.ago.to_date, :due_date => 1.week.from_now.to_date) end context ":html format" do context "todo line" do should "start from the starting point on the left" do @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4}) assert_select "div.version.task_todo[style*=left:28px]", true, @response.body end should "be the total width of the version" do @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4}) assert_select "div.version.task_todo[style*=width:58px]", true, @response.body end end context "late line" do should "start from the starting point on the left" do @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4}) assert_select "div.version.task_late[style*=left:28px]", true, @response.body end should "be the total delayed width of the version" do @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4}) assert_select "div.version.task_late[style*=width:30px]", true, @response.body end end context "done line" do should "start from the starting point on the left" do @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4}) assert_select "div.version.task_done[style*=left:28px]", true, @response.body end should "be the total done width of the version" do @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4}) assert_select "div.version.task_done[style*=width:16px]", true, @response.body end end context "starting marker" do should "not appear if the starting point is off the gantt chart" do # Shift the date range of the chart @gantt.instance_variable_set('@date_from', Date.today) @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4}) assert_select "div.version.starting", false end should "appear at the starting point" do @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4}) assert_select "div.version.starting[style*=left:28px]", true, @response.body end end context "ending marker" do should "not appear if the starting point is off the gantt chart" do # Shift the date range of the chart @gantt.instance_variable_set('@date_to', 2.weeks.ago.to_date) @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4}) assert_select "div.version.ending", false end should "appear at the end of the date range" do @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4}) assert_select "div.version.ending[style*=left:88px]", true, @response.body end end context "status content" do should "appear at the far left, even if it's far in the past" do @gantt.instance_variable_set('@date_to', 2.weeks.ago.to_date) @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4}) assert_select "div.version.label", /#{@version.name}/ end should "show the version name" do @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4}) assert_select "div.version.label", /#{@version.name}/ end should "show the percent complete" do @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4}) assert_select "div.version.label", /30%/ end end end should "test the PNG format" should "test the PDF format" end context "#subject_for_issue" do setup do create_gantt @project.enabled_module_names = [:issue_tracking] @tracker = Tracker.generate! @project.trackers << @tracker @issue = Issue.generate!(:subject => "gantt#subject_for_issue", :tracker => @tracker, :project => @project, :start_date => 3.days.ago.to_date, :due_date => Date.yesterday) @project.issues << @issue end context ":html format" do should "add an absolute positioned div" do @response.body = @gantt.subject_for_issue(@issue, {:format => :html}) assert_select "div[style*=absolute]" end should "use the indent option to move the div to the right" do @response.body = @gantt.subject_for_issue(@issue, {:format => :html, :indent => 40}) assert_select "div[style*=left:40]" end should "include the issue subject" do @response.body = @gantt.subject_for_issue(@issue, {:format => :html}) assert_select 'div', :text => /#{@issue.subject}/ end should "include a link to the issue" do @response.body = @gantt.subject_for_issue(@issue, {:format => :html}) assert_select 'a[href=?]', Regexp.escape("/issues/#{@issue.to_param}"), :text => /#{@tracker.name} ##{@issue.id}/ end should "style overdue issues" do assert @issue.overdue?, "Need an overdue issue for this test" @response.body = @gantt.subject_for_issue(@issue, {:format => :html}) assert_select 'div span.issue-overdue' end end should "test the PNG format" should "test the PDF format" end context "#line_for_issue" do setup do create_gantt @project.enabled_module_names = [:issue_tracking] @tracker = Tracker.generate! @project.trackers << @tracker @version = Version.generate!(:effective_date => 1.week.from_now.to_date) @project.versions << @version @issue = Issue.generate!(:fixed_version => @version, :subject => "gantt#line_for_project", :tracker => @tracker, :project => @project, :done_ratio => 30, :start_date => 1.week.ago.to_date, :due_date => 1.week.from_now.to_date) @project.issues << @issue end context ":html format" do context "todo line" do should "start from the starting point on the left" do @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) assert_select "div.task_todo[style*=left:28px]", true, @response.body end should "be the total width of the issue" do @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) assert_select "div.task_todo[style*=width:58px]", true, @response.body end end context "late line" do should "start from the starting point on the left" do @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) assert_select "div.task_late[style*=left:28px]", true, @response.body end should "be the total delayed width of the issue" do @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) assert_select "div.task_late[style*=width:30px]", true, @response.body end end context "done line" do should "start from the starting point on the left" do @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) assert_select "div.task_done[style*=left:28px]", true, @response.body end should "be the total done width of the issue" do @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) # 15 days * 4 px * 30% - 2 px for borders = 16 px assert_select "div.task_done[style*=width:16px]", true, @response.body end should "not be the total done width if the chart starts after issue start date" do create_gantt(@project, :date_from => 5.days.ago.to_date) @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) assert_select "div.task_done[style*=left:0px]", true, @response.body assert_select "div.task_done[style*=width:8px]", true, @response.body end context "for completed issue" do setup do @issue.done_ratio = 100 end should "be the total width of the issue" do @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) assert_select "div.task_done[style*=width:58px]", true, @response.body end should "be the total width of the issue with due_date=start_date" do @issue.due_date = @issue.start_date @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) assert_select "div.task_done[style*=width:2px]", true, @response.body end end end context "status content" do should "appear at the far left, even if it's far in the past" do @gantt.instance_variable_set('@date_to', 2.weeks.ago.to_date) @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) assert_select "div.task.label", true, @response.body end should "show the issue status" do @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) assert_select "div.task.label", /#{@issue.status.name}/ end should "show the percent complete" do @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) assert_select "div.task.label", /30%/ end end end should "have an issue tooltip" do @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) assert_select "div.tooltip", /#{@issue.subject}/ end should "test the PNG format" should "test the PDF format" end context "#to_image" do should "be tested" end context "#to_pdf" do should "be tested" end end