##// END OF EJS Templates
Do not create projects in alphabetical order in nested set tests (#12431)....
Jean-Philippe Lang -
r10638:be7895e04ec0
parent child
Show More
@@ -1,167 +1,167
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
2 # Copyright (C) 2006-2012 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 ProjectNestedSetTest < ActiveSupport::TestCase
20 class ProjectNestedSetTest < ActiveSupport::TestCase
21
21
22 def setup
22 def setup
23 Project.delete_all
23 Project.delete_all
24
24
25 @a = Project.create!(:name => 'A', :identifier => 'projecta')
25 @a = Project.create!(:name => 'A', :identifier => 'projecta')
26 @a1 = Project.create!(:name => 'A1', :identifier => 'projecta1')
26 @a1 = Project.create!(:name => 'A1', :identifier => 'projecta1')
27 @a1.set_parent!(@a)
27 @a1.set_parent!(@a)
28 @a2 = Project.create!(:name => 'A2', :identifier => 'projecta2')
28 @a2 = Project.create!(:name => 'A2', :identifier => 'projecta2')
29 @a2.set_parent!(@a)
29 @a2.set_parent!(@a)
30
30
31 @c = Project.create!(:name => 'C', :identifier => 'projectc')
32 @c1 = Project.create!(:name => 'C1', :identifier => 'projectc1')
33 @c1.set_parent!(@c)
34
31 @b = Project.create!(:name => 'B', :identifier => 'projectb')
35 @b = Project.create!(:name => 'B', :identifier => 'projectb')
36 @b2 = Project.create!(:name => 'B2', :identifier => 'projectb2')
37 @b2.set_parent!(@b)
32 @b1 = Project.create!(:name => 'B1', :identifier => 'projectb1')
38 @b1 = Project.create!(:name => 'B1', :identifier => 'projectb1')
33 @b1.set_parent!(@b)
39 @b1.set_parent!(@b)
34 @b11 = Project.create!(:name => 'B11', :identifier => 'projectb11')
40 @b11 = Project.create!(:name => 'B11', :identifier => 'projectb11')
35 @b11.set_parent!(@b1)
41 @b11.set_parent!(@b1)
36 @b2 = Project.create!(:name => 'B2', :identifier => 'projectb2')
37 @b2.set_parent!(@b)
38
39 @c = Project.create!(:name => 'C', :identifier => 'projectc')
40 @c1 = Project.create!(:name => 'C1', :identifier => 'projectc1')
41 @c1.set_parent!(@c)
42
42
43 @a, @a1, @a2, @b, @b1, @b11, @b2, @c, @c1 = *(Project.all.sort_by(&:name))
43 @a, @a1, @a2, @b, @b1, @b11, @b2, @c, @c1 = *(Project.all.sort_by(&:name))
44 end
44 end
45
45
46 def test_valid_tree
46 def test_valid_tree
47 assert_valid_nested_set
47 assert_valid_nested_set
48 end
48 end
49
49
50 def test_moving_a_child_to_a_different_parent_should_keep_valid_tree
50 def test_moving_a_child_to_a_different_parent_should_keep_valid_tree
51 assert_no_difference 'Project.count' do
51 assert_no_difference 'Project.count' do
52 Project.find_by_name('B1').set_parent!(Project.find_by_name('A2'))
52 Project.find_by_name('B1').set_parent!(Project.find_by_name('A2'))
53 end
53 end
54 assert_valid_nested_set
54 assert_valid_nested_set
55 end
55 end
56
56
57 def test_renaming_a_root_to_first_position_should_update_nested_set_order
57 def test_renaming_a_root_to_first_position_should_update_nested_set_order
58 @c.name = '1'
58 @c.name = '1'
59 @c.save!
59 @c.save!
60 assert_valid_nested_set
60 assert_valid_nested_set
61 end
61 end
62
62
63 def test_renaming_a_root_to_middle_position_should_update_nested_set_order
63 def test_renaming_a_root_to_middle_position_should_update_nested_set_order
64 @a.name = 'BA'
64 @a.name = 'BA'
65 @a.save!
65 @a.save!
66 assert_valid_nested_set
66 assert_valid_nested_set
67 end
67 end
68
68
69 def test_renaming_a_root_to_last_position_should_update_nested_set_order
69 def test_renaming_a_root_to_last_position_should_update_nested_set_order
70 @a.name = 'D'
70 @a.name = 'D'
71 @a.save!
71 @a.save!
72 assert_valid_nested_set
72 assert_valid_nested_set
73 end
73 end
74
74
75 def test_renaming_a_root_to_same_position_should_update_nested_set_order
75 def test_renaming_a_root_to_same_position_should_update_nested_set_order
76 @c.name = 'D'
76 @c.name = 'D'
77 @c.save!
77 @c.save!
78 assert_valid_nested_set
78 assert_valid_nested_set
79 end
79 end
80
80
81 def test_renaming_a_child_should_update_nested_set_order
81 def test_renaming_a_child_should_update_nested_set_order
82 @a1.name = 'A3'
82 @a1.name = 'A3'
83 @a1.save!
83 @a1.save!
84 assert_valid_nested_set
84 assert_valid_nested_set
85 end
85 end
86
86
87 def test_renaming_a_child_with_child_should_update_nested_set_order
87 def test_renaming_a_child_with_child_should_update_nested_set_order
88 @b1.name = 'B3'
88 @b1.name = 'B3'
89 @b1.save!
89 @b1.save!
90 assert_valid_nested_set
90 assert_valid_nested_set
91 end
91 end
92
92
93 def test_adding_a_root_to_first_position_should_update_nested_set_order
93 def test_adding_a_root_to_first_position_should_update_nested_set_order
94 project = Project.create!(:name => '1', :identifier => 'projectba')
94 project = Project.create!(:name => '1', :identifier => 'projectba')
95 assert_valid_nested_set
95 assert_valid_nested_set
96 end
96 end
97
97
98 def test_adding_a_root_to_middle_position_should_update_nested_set_order
98 def test_adding_a_root_to_middle_position_should_update_nested_set_order
99 project = Project.create!(:name => 'BA', :identifier => 'projectba')
99 project = Project.create!(:name => 'BA', :identifier => 'projectba')
100 assert_valid_nested_set
100 assert_valid_nested_set
101 end
101 end
102
102
103 def test_adding_a_root_to_last_position_should_update_nested_set_order
103 def test_adding_a_root_to_last_position_should_update_nested_set_order
104 project = Project.create!(:name => 'Z', :identifier => 'projectba')
104 project = Project.create!(:name => 'Z', :identifier => 'projectba')
105 assert_valid_nested_set
105 assert_valid_nested_set
106 end
106 end
107
107
108 def test_destroying_a_root_with_children_should_keep_valid_tree
108 def test_destroying_a_root_with_children_should_keep_valid_tree
109 assert_difference 'Project.count', -4 do
109 assert_difference 'Project.count', -4 do
110 Project.find_by_name('B').destroy
110 Project.find_by_name('B').destroy
111 end
111 end
112 assert_valid_nested_set
112 assert_valid_nested_set
113 end
113 end
114
114
115 def test_destroying_a_child_with_children_should_keep_valid_tree
115 def test_destroying_a_child_with_children_should_keep_valid_tree
116 assert_difference 'Project.count', -2 do
116 assert_difference 'Project.count', -2 do
117 Project.find_by_name('B1').destroy
117 Project.find_by_name('B1').destroy
118 end
118 end
119 assert_valid_nested_set
119 assert_valid_nested_set
120 end
120 end
121
121
122 private
122 private
123
123
124 def assert_nested_set_values(h)
124 def assert_nested_set_values(h)
125 assert Project.valid?
125 assert Project.valid?
126 h.each do |project, expected|
126 h.each do |project, expected|
127 project.reload
127 project.reload
128 assert_equal expected, [project.parent_id, project.lft, project.rgt], "Unexpected nested set values for #{project.name}"
128 assert_equal expected, [project.parent_id, project.lft, project.rgt], "Unexpected nested set values for #{project.name}"
129 end
129 end
130 end
130 end
131
131
132 def assert_valid_nested_set
132 def assert_valid_nested_set
133 projects = Project.all
133 projects = Project.all
134 lft_rgt = projects.map {|p| [p.lft, p.rgt]}.flatten
134 lft_rgt = projects.map {|p| [p.lft, p.rgt]}.flatten
135 assert_equal projects.size * 2, lft_rgt.uniq.size
135 assert_equal projects.size * 2, lft_rgt.uniq.size
136 assert_equal 1, lft_rgt.min
136 assert_equal 1, lft_rgt.min
137 assert_equal projects.size * 2, lft_rgt.max
137 assert_equal projects.size * 2, lft_rgt.max
138
138
139 projects.each do |project|
139 projects.each do |project|
140 # lft should always be < rgt
140 # lft should always be < rgt
141 assert project.lft < project.rgt, "lft=#{project.lft} was not < rgt=#{project.rgt} for project #{project.name}"
141 assert project.lft < project.rgt, "lft=#{project.lft} was not < rgt=#{project.rgt} for project #{project.name}"
142 if project.parent_id
142 if project.parent_id
143 # child lft/rgt values must be greater/lower
143 # child lft/rgt values must be greater/lower
144 assert_not_nil project.parent, "parent was nil for project #{project.name}"
144 assert_not_nil project.parent, "parent was nil for project #{project.name}"
145 assert project.lft > project.parent.lft, "lft=#{project.lft} was not > parent.lft=#{project.parent.lft} for project #{project.name}"
145 assert project.lft > project.parent.lft, "lft=#{project.lft} was not > parent.lft=#{project.parent.lft} for project #{project.name}"
146 assert project.rgt < project.parent.rgt, "rgt=#{project.rgt} was not < parent.rgt=#{project.parent.rgt} for project #{project.name}"
146 assert project.rgt < project.parent.rgt, "rgt=#{project.rgt} was not < parent.rgt=#{project.parent.rgt} for project #{project.name}"
147 end
147 end
148 # no overlapping lft/rgt values
148 # no overlapping lft/rgt values
149 overlapping = projects.detect {|other|
149 overlapping = projects.detect {|other|
150 other != project && (
150 other != project && (
151 (other.lft > project.lft && other.lft < project.rgt && other.rgt > project.rgt) ||
151 (other.lft > project.lft && other.lft < project.rgt && other.rgt > project.rgt) ||
152 (other.rgt > project.lft && other.rgt < project.rgt && other.lft < project.lft)
152 (other.rgt > project.lft && other.rgt < project.rgt && other.lft < project.lft)
153 )
153 )
154 }
154 }
155 assert_nil overlapping, (overlapping && "Project #{overlapping.name} (#{overlapping.lft}/#{overlapping.rgt}) overlapped #{project.name} (#{project.lft}/#{project.rgt})")
155 assert_nil overlapping, (overlapping && "Project #{overlapping.name} (#{overlapping.lft}/#{overlapping.rgt}) overlapped #{project.name} (#{project.lft}/#{project.rgt})")
156 end
156 end
157
157
158 # root projects sorted alphabetically
158 # root projects sorted alphabetically
159 assert_equal Project.roots.map(&:name).sort, Project.roots.sort_by(&:lft).map(&:name), "Root projects were not properly sorted"
159 assert_equal Project.roots.map(&:name).sort, Project.roots.sort_by(&:lft).map(&:name), "Root projects were not properly sorted"
160 projects.each do |project|
160 projects.each do |project|
161 if project.children.any?
161 if project.children.any?
162 # sibling projects sorted alphabetically
162 # sibling projects sorted alphabetically
163 assert_equal project.children.map(&:name).sort, project.children.order('lft').map(&:name), "Project #{project.name}'s children were not properly sorted"
163 assert_equal project.children.map(&:name).sort, project.children.order('lft').map(&:name), "Project #{project.name}'s children were not properly sorted"
164 end
164 end
165 end
165 end
166 end
166 end
167 end
167 end
General Comments 0
You need to be logged in to leave comments. Login now