From cd46d30f5fc98765fa0d7c4b67856ddf091e7392 Mon Sep 17 00:00:00 2001 From: Kirill Marchuk <62mkv@mail.ru> Date: Mon, 30 Nov 2015 23:15:11 +0600 Subject: Added method "Issue.blocks_or_precedes"; changed issue validation; added unit tests --- app/models/issue.rb | 27 ++++++++++++++++++++++++++- test/unit/issue_test.rb | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/app/models/issue.rb b/app/models/issue.rb index 707c458..83fd357 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -660,7 +660,7 @@ class Issue < ActiveRecord::Base elsif @parent_issue if !valid_parent_project?(@parent_issue) errors.add :parent_issue_id, :invalid - elsif (@parent_issue != parent) && (all_dependent_issues.include?(@parent_issue) || @parent_issue.all_dependent_issues.include?(self)) + elsif (@parent_issue != parent) && (@parent_issue.blocks_or_precedes?(self)) errors.add :parent_issue_id, :invalid elsif !new_record? # moving an existing issue @@ -1132,6 +1132,31 @@ class Issue < ActiveRecord::Base dependencies end + # Returns true if this issue blocks or precedes another issue, otherwise returns false + def blocks_or_precedes?(other) + return true if self == other + i_all = [self] + i_last = [self] + while i_last.length>0 do + i_current = [] + i_last.collect do |i| + i.relations_from.find_all {|ir| ir.relation_type == IssueRelation::TYPE_PRECEDES || ir.relation_type == IssueRelation::TYPE_BLOCKS }. + collect { |ir| ir.issue_to }. + collect { |i| i_current << i if (!i_all.include? i) && (!i_last.include? i) && (!i_current.include? i)} + end + + # collect parents for all of the "last" issues + i_last.collect { |i| i_current << Issue.find_by_id(i.parent_issue_id) if !i.parent_issue_id.nil? } + + return true if i_current.include? other + + i_last = i_current + i_all = i_all.concat(i_last) + end + + return false + end + # Returns an array of issues that duplicate this one def duplicates relations_to.select {|r| r.relation_type == IssueRelation::TYPE_DUPLICATES}.collect {|r| r.issue_from} diff --git a/test/unit/issue_test.rb b/test/unit/issue_test.rb index 1dea102..55f2b69 100644 --- a/test/unit/issue_test.rb +++ b/test/unit/issue_test.rb @@ -1690,6 +1690,35 @@ class IssueTest < ActiveSupport::TestCase assert closed_statuses.empty? end +def test_blocks_or_precedes_with_parent + issue1 = Issue.generate! + issue2 = Issue.generate! + issue3 = Issue.generate! + issue4 = Issue.generate! + + IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES) + issue2.parent_issue_id = issue3.id + issue2.save + IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_BLOCKS) + + assert issue1.blocks_or_precedes?(issue2), "issue1 should be blocking/preceding issue2" + assert issue1.blocks_or_precedes?(issue3), "issue1 should be blocking/preceding issue3" + assert issue1.blocks_or_precedes?(issue4), "issue1 should be blocking/preceding issue4" + + assert !issue2.blocks_or_precedes?(issue1), "issue2 should NOT be blocking/preceding issue1" + assert issue2.blocks_or_precedes?(issue3), "issue2 should be blocking/preceding issue3" + assert issue2.blocks_or_precedes?(issue4), "issue2 should be blocking/preceding issue4" + + assert !issue3.blocks_or_precedes?(issue1), "issue3 should NOT be blocking/preceding issue1" + assert !issue3.blocks_or_precedes?(issue2), "issue3 should NOT be blocking/preceding issue2" + assert issue3.blocks_or_precedes?(issue4), "issue3 should be blocking/preceding issue4" + + assert !issue4.blocks_or_precedes?(issue1), "issue4 should be blocking/preceding issue1" + assert !issue4.blocks_or_precedes?(issue2), "issue4 should be blocking/preceding issue2" + assert !issue4.blocks_or_precedes?(issue3), "issue4 should be blocking/preceding issue3" + + end + def test_unblocked_issues_allow_closed_statuses blocking_issue = Issue.find(10) @@ -1848,19 +1877,21 @@ class IssueTest < ActiveSupport::TestCase end end - def test_setting_parent_to_a_dependent_issue_should_not_validate + # this is to make sure that Defect #13654 is Solved + def test_setting_parent_to_a_parent_of_related_issue_should_validate set_language_if_valid 'en' issue1 = Issue.generate! issue2 = Issue.generate! + issue2.parent_issue_id = issue1.id + issue2.save! issue3 = Issue.generate! - IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES) - IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES) + IssueRelation.create!(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES) issue3.reload issue3.parent_issue_id = issue2.id - assert !issue3.valid? - assert_include 'Parent task is invalid', issue3.errors.full_messages + assert issue3.valid? end + # this is to make sure that Defect #8794 is Solved def test_setting_parent_should_not_allow_circular_dependency set_language_if_valid 'en' issue1 = Issue.generate! -- 1.9.4.msysgit.2