##// END OF EJS Templates
Fixed "column specified more than once" error with SQLServer (#6579)....
Jean-Philippe Lang -
r12878:96baa905bf5b
parent child
Show More
@@ -1,183 +1,183
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class ProjectNestedSetTest < ActiveSupport::TestCase
21 21
22 22 def setup
23 23 Project.delete_all
24 24
25 25 @a = Project.create!(:name => 'A', :identifier => 'projecta')
26 26 @a1 = Project.create!(:name => 'A1', :identifier => 'projecta1')
27 27 @a1.set_parent!(@a)
28 28 @a2 = Project.create!(:name => 'A2', :identifier => 'projecta2')
29 29 @a2.set_parent!(@a)
30 30
31 31 @c = Project.create!(:name => 'C', :identifier => 'projectc')
32 32 @c1 = Project.create!(:name => 'C1', :identifier => 'projectc1')
33 33 @c1.set_parent!(@c)
34 34
35 35 @b = Project.create!(:name => 'B', :identifier => 'projectb')
36 36 @b2 = Project.create!(:name => 'B2', :identifier => 'projectb2')
37 37 @b2.set_parent!(@b)
38 38 @b1 = Project.create!(:name => 'B1', :identifier => 'projectb1')
39 39 @b1.set_parent!(@b)
40 40 @b11 = Project.create!(:name => 'B11', :identifier => 'projectb11')
41 41 @b11.set_parent!(@b1)
42 42
43 43 @a, @a1, @a2, @b, @b1, @b11, @b2, @c, @c1 = *(Project.all.sort_by(&:name))
44 44 end
45 45
46 46 def test_valid_tree
47 47 assert_valid_nested_set
48 48 end
49 49
50 50 def test_rebuild_should_build_valid_tree
51 51 Project.update_all "lft = NULL, rgt = NULL"
52 52
53 53 Project.rebuild_tree!
54 54 assert_valid_nested_set
55 55 end
56 56
57 57 def test_rebuild_tree_should_build_valid_tree_even_with_valid_lft_rgt_values
58 58 Project.where({:id => @a.id }).update_all("name = 'YY'")
59 59 # lft and rgt values are still valid (Project.rebuild! would not update anything)
60 60 # but projects are not ordered properly (YY is in the first place)
61 61
62 62 Project.rebuild_tree!
63 63 assert_valid_nested_set
64 64 end
65 65
66 66 def test_moving_a_child_to_a_different_parent_should_keep_valid_tree
67 67 assert_no_difference 'Project.count' do
68 68 Project.find_by_name('B1').set_parent!(Project.find_by_name('A2'))
69 69 end
70 70 assert_valid_nested_set
71 71 end
72 72
73 73 def test_renaming_a_root_to_first_position_should_update_nested_set_order
74 74 @c.name = '1'
75 75 @c.save!
76 76 assert_valid_nested_set
77 77 end
78 78
79 79 def test_renaming_a_root_to_middle_position_should_update_nested_set_order
80 80 @a.name = 'BA'
81 81 @a.save!
82 82 assert_valid_nested_set
83 83 end
84 84
85 85 def test_renaming_a_root_to_last_position_should_update_nested_set_order
86 86 @a.name = 'D'
87 87 @a.save!
88 88 assert_valid_nested_set
89 89 end
90 90
91 91 def test_renaming_a_root_to_same_position_should_update_nested_set_order
92 92 @c.name = 'D'
93 93 @c.save!
94 94 assert_valid_nested_set
95 95 end
96 96
97 97 def test_renaming_a_child_should_update_nested_set_order
98 98 @a1.name = 'A3'
99 99 @a1.save!
100 100 assert_valid_nested_set
101 101 end
102 102
103 103 def test_renaming_a_child_with_child_should_update_nested_set_order
104 104 @b1.name = 'B3'
105 105 @b1.save!
106 106 assert_valid_nested_set
107 107 end
108 108
109 109 def test_adding_a_root_to_first_position_should_update_nested_set_order
110 110 project = Project.create!(:name => '1', :identifier => 'projectba')
111 111 assert_valid_nested_set
112 112 end
113 113
114 114 def test_adding_a_root_to_middle_position_should_update_nested_set_order
115 115 project = Project.create!(:name => 'BA', :identifier => 'projectba')
116 116 assert_valid_nested_set
117 117 end
118 118
119 119 def test_adding_a_root_to_last_position_should_update_nested_set_order
120 120 project = Project.create!(:name => 'Z', :identifier => 'projectba')
121 121 assert_valid_nested_set
122 122 end
123 123
124 124 def test_destroying_a_root_with_children_should_keep_valid_tree
125 125 assert_difference 'Project.count', -4 do
126 126 Project.find_by_name('B').destroy
127 127 end
128 128 assert_valid_nested_set
129 129 end
130 130
131 131 def test_destroying_a_child_with_children_should_keep_valid_tree
132 132 assert_difference 'Project.count', -2 do
133 133 Project.find_by_name('B1').destroy
134 134 end
135 135 assert_valid_nested_set
136 136 end
137 137
138 138 private
139 139
140 140 def assert_nested_set_values(h)
141 141 assert Project.valid?
142 142 h.each do |project, expected|
143 143 project.reload
144 144 assert_equal expected, [project.parent_id, project.lft, project.rgt], "Unexpected nested set values for #{project.name}"
145 145 end
146 146 end
147 147
148 148 def assert_valid_nested_set
149 149 projects = Project.all
150 150 lft_rgt = projects.map {|p| [p.lft, p.rgt]}.flatten
151 151 assert_equal projects.size * 2, lft_rgt.uniq.size
152 152 assert_equal 1, lft_rgt.min
153 153 assert_equal projects.size * 2, lft_rgt.max
154 154
155 155 projects.each do |project|
156 156 # lft should always be < rgt
157 157 assert project.lft < project.rgt, "lft=#{project.lft} was not < rgt=#{project.rgt} for project #{project.name}"
158 158 if project.parent_id
159 159 # child lft/rgt values must be greater/lower
160 160 assert_not_nil project.parent, "parent was nil for project #{project.name}"
161 161 assert project.lft > project.parent.lft, "lft=#{project.lft} was not > parent.lft=#{project.parent.lft} for project #{project.name}"
162 162 assert project.rgt < project.parent.rgt, "rgt=#{project.rgt} was not < parent.rgt=#{project.parent.rgt} for project #{project.name}"
163 163 end
164 164 # no overlapping lft/rgt values
165 165 overlapping = projects.detect {|other|
166 166 other != project && (
167 167 (other.lft > project.lft && other.lft < project.rgt && other.rgt > project.rgt) ||
168 168 (other.rgt > project.lft && other.rgt < project.rgt && other.lft < project.lft)
169 169 )
170 170 }
171 171 assert_nil overlapping, (overlapping && "Project #{overlapping.name} (#{overlapping.lft}/#{overlapping.rgt}) overlapped #{project.name} (#{project.lft}/#{project.rgt})")
172 172 end
173 173
174 174 # root projects sorted alphabetically
175 175 assert_equal Project.roots.map(&:name).sort, Project.roots.sort_by(&:lft).map(&:name), "Root projects were not properly sorted"
176 176 projects.each do |project|
177 177 if project.children.any?
178 178 # sibling projects sorted alphabetically
179 assert_equal project.children.map(&:name).sort, project.children.order('lft').map(&:name), "Project #{project.name}'s children were not properly sorted"
179 assert_equal project.children.map(&:name).sort, project.children.sort_by(&:lft).map(&:name), "Project #{project.name}'s children were not properly sorted"
180 180 end
181 181 end
182 182 end
183 183 end
General Comments 0
You need to be logged in to leave comments. Login now