|
|
|
#-- encoding: UTF-8
|
|
|
|
#-- copyright
|
|
|
|
# OpenProject is a project management system.
|
|
|
|
#
|
|
|
|
# Copyright (C) 2012-2013 the OpenProject Team
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or
|
|
|
|
# modify it under the terms of the GNU General Public License version 3.
|
|
|
|
#
|
|
|
|
# See doc/COPYRIGHT.rdoc for more details.
|
|
|
|
#++
|
|
|
|
|
|
|
|
require File.dirname(__FILE__) + '/../spec_helper'
|
|
|
|
|
|
|
|
describe WorkPackage, "rebuilding nested set" do
|
|
|
|
let(:project) { FactoryGirl.create(:valid_project) }
|
|
|
|
let(:status) { FactoryGirl.create(:issue_status) }
|
|
|
|
let(:priority) { FactoryGirl.create(:priority) }
|
|
|
|
let(:type) { project.types.first }
|
|
|
|
let(:author) { FactoryGirl.create(:user) }
|
|
|
|
|
|
|
|
def issue_factory(parent = nil)
|
|
|
|
FactoryGirl.create(:issue, :status => status,
|
|
|
|
:project => project,
|
|
|
|
:priority => priority,
|
|
|
|
:author => author,
|
|
|
|
:type => type,
|
|
|
|
:parent => parent)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:root_1) { issue_factory }
|
|
|
|
let(:root_2) { issue_factory }
|
|
|
|
let(:child_1_1) { issue_factory(root_1) }
|
|
|
|
let(:child_1_2) { issue_factory(root_1) }
|
|
|
|
let(:child_2_1) { issue_factory(root_2) }
|
|
|
|
let(:gchild_1_1_1) { issue_factory(child_1_1) }
|
|
|
|
let(:ggchild_1_1_1_1) { issue_factory(gchild_1_1_1) }
|
|
|
|
let(:gchild_1_1_2) { issue_factory(child_1_1) }
|
|
|
|
let(:gchild_1_2_1) { issue_factory(child_1_2) }
|
|
|
|
let(:gchild_2_1_1) { issue_factory(child_2_1) }
|
|
|
|
|
|
|
|
describe :valid? do
|
|
|
|
describe "WITH one root issue" do
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH two one node trees" do
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
root_2
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issue deep tree" do
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a three issue deep tree" do
|
|
|
|
before do
|
|
|
|
gchild_1_1_1
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issue deep tree
|
|
|
|
WITH the left value of the child beeing invalid" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => root_1.lft }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should_not be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issue deep tree
|
|
|
|
WITH the right value of the child beeing invalid" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :rgt => 18 }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should_not be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issue deep tree
|
|
|
|
WITH the root_id of the child pointing to itself" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :root_id => child_1_1.id }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should_not be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a three issue deep tree
|
|
|
|
WITH the root_id of the grand child pointing to the child" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :root_id => child_1_1.id }, { :id => gchild_1_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should_not be_valid }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe :rebuild! do
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the left value of the child beeing invalid" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => root_1.lft }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.rebuild!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe :rebuild_silently! do
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the left value of the child beeing invalid" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => root_1.lft }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the left value of the root beeing invalid
|
|
|
|
WITH an estimated_hours values set for the root after the tree got broken" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => child_1_1.lft }, { :id => root_1.id })
|
|
|
|
Issue.update_all({ :estimated_hours => 1.0 }, { :id => root_1.id })
|
|
|
|
|
|
|
|
Issue.rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the right value of the root beeing invalid
|
|
|
|
WITH an estimated_hours values set for the root after the tree got broken" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :rgt => child_1_1.lft }, { :id => root_1.id })
|
|
|
|
Issue.update_all({ :estimated_hours => 1.0 }, { :id => root_1.id })
|
|
|
|
|
|
|
|
Issue.rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the root_id value of the child pointing to itself" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :root_id => child_1_1.id }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a three issues deep tree
|
|
|
|
WITH the root_id value of the grandchild pointing to itself" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :root_id => gchild_1_1_1.id }, { :id => gchild_1_1_1.id })
|
|
|
|
|
|
|
|
Issue.rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a three issues deep tree
|
|
|
|
WITH the root_id value of the grandchild pointing to the child" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :root_id => child_1_1.id }, { :id => gchild_1_1_1.id })
|
|
|
|
|
|
|
|
Issue.rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH two three issues deep trees
|
|
|
|
WITH the root_id value of each grandchildren pointing to the children
|
|
|
|
WITH selecting to fix only one tree" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
gchild_1_1_1
|
|
|
|
gchild_2_1_1
|
|
|
|
Issue.update_all({ :root_id => child_1_1.id }, { :id => gchild_1_1_1.id })
|
|
|
|
Issue.update_all({ :root_id => child_2_1.id }, { :id => gchild_2_1_1.id })
|
|
|
|
|
|
|
|
Issue.rebuild_silently!(root_1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { gchild_1_1_1.reload.root_id.should == root_1.id }
|
|
|
|
it { gchild_2_1_1.reload.root_id.should == child_2_1.id }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH two three issues deep trees
|
|
|
|
WITH the right value of each grandchildren beeing equal to the left value
|
|
|
|
WITH selecting to fix only one tree" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
gchild_1_1_1
|
|
|
|
gchild_2_1_1
|
|
|
|
Issue.update_all({ :rgt => gchild_1_1_1.lft }, { :id => gchild_1_1_1.id })
|
|
|
|
Issue.update_all({ :rgt => gchild_2_1_1.lft }, { :id => gchild_2_1_1.id })
|
|
|
|
|
|
|
|
Issue.rebuild_silently!(root_1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { gchild_1_1_1.reload.rgt.should == gchild_1_1_1.lft + 1 }
|
|
|
|
it { gchild_2_1_1.reload.rgt.should == gchild_2_1_1.lft }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe :selectively_rebuild_silently! do
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the left value of the child beeing invalid" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => root_1.lft }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the left value of the root beeing invalid
|
|
|
|
WITH an estimated_hours values set for the root after the tree got broken" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => child_1_1.lft }, { :id => root_1.id })
|
|
|
|
Issue.update_all({ :estimated_hours => 1.0 }, { :id => root_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the right value of the root beeing invalid
|
|
|
|
WITH an estimated_hours values set for the root after the tree got broken" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :rgt => child_1_1.lft }, { :id => root_1.id })
|
|
|
|
Issue.update_all({ :estimated_hours => 1.0 }, { :id => root_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the root_id value of the child pointing to itself" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :root_id => child_1_1.id }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a three issues deep tree
|
|
|
|
WITH the root_id value of the grandchild pointing to itself" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :root_id => gchild_1_1_1.id }, { :id => gchild_1_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a three issues deep tree
|
|
|
|
WITH the root_id value of the grandchild pointing to the child" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :root_id => child_1_1.id }, { :id => gchild_1_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a one issue deep tree
|
|
|
|
WITH the root_id beeing null" do
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
|
|
|
|
Issue.update_all({ :root_id => nil }, { :id => root_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH two one issue deep trees
|
|
|
|
WITH the root_id beeing of one pointing to the other" do
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
root_2
|
|
|
|
|
|
|
|
Issue.update_all({ :root_id => root_2.id }, { :id => root_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issue deep tree
|
|
|
|
WITH the root_id of the child pointing to itself" do
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
|
|
|
|
Issue.update_all({ :root_id => child_1_1.id }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a tree issue deep tree
|
|
|
|
WITH the root_id of the child pointing to another tree
|
|
|
|
WITH the root_id of the grandchild pointing to the same other tree" do
|
|
|
|
before do
|
|
|
|
gchild_1_1_1
|
|
|
|
|
|
|
|
Issue.update_all({ :root_id => 0 }, { :id => child_1_1.id })
|
|
|
|
Issue.update_all({ :root_id => 0 }, { :id => gchild_1_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issue deep tree
|
|
|
|
WITH a one issue deep tree
|
|
|
|
WITH the root_id of the child pointing to the other tree" do
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
root_2
|
|
|
|
|
|
|
|
Issue.update_all({ :root_id => root_2.id }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a one issue deep tree
|
|
|
|
WITH right > left" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => 2, :rgt => 1 }, { :id => root_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH everything ok" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's right > left" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => 4, :rgt => 3 }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's right = left" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => 3, :rgt => 3 }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's right beeing null" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :rgt => nil }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's left beeing null" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => nil }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's right beeing equal to the root's right" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
Issue.update_all({ :rgt => root_1.reload.rgt }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's right beeing larger than the root's right" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
Issue.update_all({ :rgt => root_1.reload.rgt + 1 }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's left beeing equal to the root's left" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
Issue.update_all({ :lft => root_1.reload.lft }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's left beeing less than the root's right" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
Issue.update_all({ :rgt => root_1.reload.lft - 1 }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's left beeing equal to the root's left" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
Issue.update_all({ :lft => root_1.reload.lft }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's right beeing equal to the root's right" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
Issue.update_all({ :rgt => root_1.reload.rgt }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a three issues deep tree
|
|
|
|
WITH the child's right beeing equal to the grandchild's right" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
gchild_1_1_1
|
|
|
|
Issue.update_all({ :rgt => gchild_1_1_1.reload.rgt }, { :id => child_1_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH two one issues deep tree
|
|
|
|
WITH the two trees in the same scope (should not happen for issues)
|
|
|
|
WITH the left of the one being the right of the other" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
root_2
|
|
|
|
|
|
|
|
Issue.update_all({ :lft => root_1.lft, :root_id => root_1.id }, { :id => root_2.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH two one issues deep tree
|
|
|
|
WITH the two trees in the same scope (should not happen for issues)
|
|
|
|
WITH the right of the one being the lft of the other" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
root_2
|
|
|
|
|
|
|
|
Issue.update_all({ :rgt => root_2.lft, :root_id => root_2.id }, { :id => root_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH one one issue deep tree
|
|
|
|
WITH one two issues deep tree
|
|
|
|
WITH the two trees in the same scope (should not happen for issues)
|
|
|
|
WITH the left of the one between left and right of the other" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
root_2
|
|
|
|
|
|
|
|
Issue.update_all({ :lft => child_1_1.lft, :root_id => root_1.id }, { :id => root_2.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH one one issue deep tree
|
|
|
|
WITH one two issues deep tree
|
|
|
|
WITH the two trees in the same scope (should not happen for issues)
|
|
|
|
WITH the right of the one between left and right of the other" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
child_2_1
|
|
|
|
|
|
|
|
Issue.update_all({ :rgt => child_2_1.rgt, :root_id => root_2.id}, { :id => root_1.id })
|
|
|
|
|
|
|
|
Issue.selectively_rebuild_silently!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.should be_valid }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe :invalid_left_and_rights do
|
|
|
|
describe "WITH a one issue deep tree
|
|
|
|
WITH right > left" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => 2, :rgt => 1 }, { :id => root_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_left_and_rights.map(&:id).should =~ [root_1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH everything ok" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_left_and_rights.map(&:id).should =~ [] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's right > left" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => 4, :rgt => 3 }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_left_and_rights.map(&:id).should =~ [child_1_1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's right = left" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => 3, :rgt => 3 }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_left_and_rights.map(&:id).should =~ [child_1_1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's right beeing null" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :rgt => nil }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_left_and_rights.map(&:id).should =~ [child_1_1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's left beeing null" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
Issue.update_all({ :lft => nil }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_left_and_rights.map(&:id).should =~ [child_1_1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's right beeing equal to the root's right" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
Issue.update_all({ :rgt => root_1.reload.rgt }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_left_and_rights.map(&:id).should =~ [child_1_1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's right beeing larger than the root's right" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
Issue.update_all({ :rgt => root_1.reload.rgt + 1 }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_left_and_rights.map(&:id).should =~ [child_1_1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's left beeing equal to the root's left" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
Issue.update_all({ :lft => root_1.reload.lft }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_left_and_rights.map(&:id).should =~ [child_1_1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's left beeing less than the root's right" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
Issue.update_all({ :rgt => root_1.reload.lft - 1 }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_left_and_rights.map(&:id).should =~ [child_1_1.id] }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe :invalid_duplicates_in_columns do
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's left beeing equal to the root's left" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
Issue.update_all({ :lft => root_1.reload.lft }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_duplicates_in_columns.map(&:id).should =~ [root_1.id, child_1_1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issues deep tree
|
|
|
|
WITH the child's right beeing equal to the root's right" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
Issue.update_all({ :rgt => root_1.reload.rgt }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_duplicates_in_columns.map(&:id).should =~ [root_1.id, child_1_1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH two one issue deep tree
|
|
|
|
WITH everything ok" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
root_2
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_duplicates_in_columns.map(&:id).should =~ [] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a three issues deep tree
|
|
|
|
WITH the child's right beeing equal to the grandchild's right" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
gchild_1_1_1
|
|
|
|
Issue.update_all({ :rgt => gchild_1_1_1.reload.rgt }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_duplicates_in_columns.map(&:id).should =~ [child_1_1.id, gchild_1_1_1.id] }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe :invalid_roots do
|
|
|
|
describe "WITH two one issues deep tree
|
|
|
|
WITH everything ok" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
root_2
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_roots.should be_empty }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH two one issues deep tree
|
|
|
|
WITH the two trees in the same scope (should not happen for issues)
|
|
|
|
WITH the left of the one being the right of the other" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
root_2
|
|
|
|
|
|
|
|
Issue.update_all({ :lft => root_1.lft, :root_id => root_1.id }, { :id => root_2.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_roots.map(&:id).should =~ [root_1.id, root_2.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH two one issues deep tree
|
|
|
|
WITH the two trees in the same scope (should not happen for issues)
|
|
|
|
WITH the right of the one being the lft of the other" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
root_2
|
|
|
|
|
|
|
|
Issue.update_all({ :rgt => root_2.lft, :root_id => root_2.id }, { :id => root_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_roots.map(&:id).should =~ [root_1.id, root_2.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH one one issue deep tree
|
|
|
|
WITH one two issues deep tree
|
|
|
|
WITH the two trees in the same scope (should not happen for issues)
|
|
|
|
WITH the left of the one between left and right of the other" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
root_2
|
|
|
|
|
|
|
|
Issue.update_all({ :lft => child_1_1.lft, :root_id => root_1.id }, { :id => root_2.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_roots.map(&:id).should =~ [root_1.id, root_2.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH one one issue deep tree
|
|
|
|
WITH one two issues deep tree
|
|
|
|
WITH the two trees in the same scope (should not happen for issues)
|
|
|
|
WITH the right of the one between left and right of the other" do
|
|
|
|
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
child_2_1
|
|
|
|
|
|
|
|
Issue.update_all({ :rgt => child_2_1.rgt, :root_id => root_2.id}, { :id => root_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_roots.map(&:id).should =~ [root_1.id, root_2.id] }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe :invalid_root_ids do
|
|
|
|
describe "WITH a one issue deep tree
|
|
|
|
WITH everything ok" do
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_root_ids.should be_empty }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issue deep tree
|
|
|
|
WITH everything ok" do
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_root_ids.should be_empty }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a three issue deep tree
|
|
|
|
WITH everything ok" do
|
|
|
|
before do
|
|
|
|
gchild_1_1_1
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_root_ids.should be_empty }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a one issue deep tree
|
|
|
|
WITH the root_id beeing null" do
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
|
|
|
|
Issue.update_all({ :root_id => nil }, { :id => root_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_root_ids.should be_empty }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH two one issue deep trees
|
|
|
|
WITH the root_id beeing of one pointing to the other" do
|
|
|
|
before do
|
|
|
|
root_1
|
|
|
|
root_2
|
|
|
|
|
|
|
|
Issue.update_all({ :root_id => root_2.id }, { :id => root_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_root_ids.map(&:id).should =~ [root_1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issue deep tree
|
|
|
|
WITH the root_id of the child pointing to itself" do
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
|
|
|
|
Issue.update_all({ :root_id => child_1_1.id }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_root_ids.map(&:id).should =~ [child_1_1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "WITH a two issue deep tree
|
|
|
|
WITH a one issue deep tree
|
|
|
|
WITH the root_id of the child pointing to the other tree" do
|
|
|
|
before do
|
|
|
|
child_1_1
|
|
|
|
root_2
|
|
|
|
|
|
|
|
Issue.update_all({ :root_id => root_2.id }, { :id => child_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
it { Issue.invalid_root_ids.map(&:id).should =~ [child_1_1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
describe "WITH a three issue deep tree
|
|
|
|
WITH the root_id of the child pointing to another tree
|
|
|
|
WITH the root_id of the grandchild pointing to the same other tree" do
|
|
|
|
before do
|
|
|
|
gchild_1_1_1
|
|
|
|
|
|
|
|
Issue.update_all({ :root_id => 0 }, { :id => child_1_1.id })
|
|
|
|
Issue.update_all({ :root_id => 0 }, { :id => gchild_1_1_1.id })
|
|
|
|
end
|
|
|
|
|
|
|
|
# As the sql statements do not work recursively
|
|
|
|
# we are currently only able to spot the child
|
|
|
|
# this is not how it should be
|
|
|
|
it { Issue.invalid_root_ids.map(&:id).should =~ [child_1_1.id] }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|