comparison test/unit/query_test.rb @ 1526:404aa68d4227

Merge from live branch
author Chris Cannam
date Thu, 11 Sep 2014 12:46:20 +0100
parents dffacf8a6908
children
comparison
equal deleted inserted replaced
1493:a5f2bdf3b486 1526:404aa68d4227
1 # Redmine - project management software 1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang 2 # Copyright (C) 2006-2014 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.
26 :watchers, :custom_fields, :custom_values, :versions, 26 :watchers, :custom_fields, :custom_values, :versions,
27 :queries, 27 :queries,
28 :projects_trackers, 28 :projects_trackers,
29 :custom_fields_trackers 29 :custom_fields_trackers
30 30
31 def test_query_with_roles_visibility_should_validate_roles
32 set_language_if_valid 'en'
33 query = IssueQuery.new(:name => 'Query', :visibility => IssueQuery::VISIBILITY_ROLES)
34 assert !query.save
35 assert_include "Roles can't be blank", query.errors.full_messages
36 query.role_ids = [1, 2]
37 assert query.save
38 end
39
40 def test_changing_roles_visibility_should_clear_roles
41 query = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_ROLES, :role_ids => [1, 2])
42 assert_equal 2, query.roles.count
43
44 query.visibility = IssueQuery::VISIBILITY_PUBLIC
45 query.save!
46 assert_equal 0, query.roles.count
47 end
48
49 def test_available_filters_should_be_ordered
50 set_language_if_valid 'en'
51 query = IssueQuery.new
52 assert_equal 0, query.available_filters.keys.index('status_id')
53 expected_order = [
54 "Status",
55 "Project",
56 "Tracker",
57 "Priority"
58 ]
59 assert_equal expected_order,
60 (query.available_filters.values.map{|v| v[:name]} & expected_order)
61 end
62
63 def test_available_filters_with_custom_fields_should_be_ordered
64 set_language_if_valid 'en'
65 UserCustomField.create!(
66 :name => 'order test', :field_format => 'string',
67 :is_for_all => true, :is_filter => true
68 )
69 query = IssueQuery.new
70 expected_order = [
71 "Searchable field",
72 "Database",
73 "Project's Development status",
74 "Author's order test",
75 "Assignee's order test"
76 ]
77 assert_equal expected_order,
78 (query.available_filters.values.map{|v| v[:name]} & expected_order)
79 end
80
31 def test_custom_fields_for_all_projects_should_be_available_in_global_queries 81 def test_custom_fields_for_all_projects_should_be_available_in_global_queries
32 query = Query.new(:project => nil, :name => '_') 82 query = IssueQuery.new(:project => nil, :name => '_')
33 assert query.available_filters.has_key?('cf_1') 83 assert query.available_filters.has_key?('cf_1')
34 assert !query.available_filters.has_key?('cf_3') 84 assert !query.available_filters.has_key?('cf_3')
35 end 85 end
36 86
37 def test_system_shared_versions_should_be_available_in_global_queries 87 def test_system_shared_versions_should_be_available_in_global_queries
38 Version.find(2).update_attribute :sharing, 'system' 88 Version.find(2).update_attribute :sharing, 'system'
39 query = Query.new(:project => nil, :name => '_') 89 query = IssueQuery.new(:project => nil, :name => '_')
40 assert query.available_filters.has_key?('fixed_version_id') 90 assert query.available_filters.has_key?('fixed_version_id')
41 assert query.available_filters['fixed_version_id'][:values].detect {|v| v.last == '2'} 91 assert query.available_filters['fixed_version_id'][:values].detect {|v| v.last == '2'}
42 end 92 end
43 93
44 def test_project_filter_in_global_queries 94 def test_project_filter_in_global_queries
45 query = Query.new(:project => nil, :name => '_') 95 query = IssueQuery.new(:project => nil, :name => '_')
46 project_filter = query.available_filters["project_id"] 96 project_filter = query.available_filters["project_id"]
47 assert_not_nil project_filter 97 assert_not_nil project_filter
48 project_ids = project_filter[:values].map{|p| p[1]} 98 project_ids = project_filter[:values].map{|p| p[1]}
49 assert project_ids.include?("1") #public project 99 assert project_ids.include?("1") #public project
50 assert !project_ids.include?("2") #private project user cannot see 100 assert !project_ids.include?("2") #private project user cannot see
61 find_issues_with_query(query) 111 find_issues_with_query(query)
62 end 112 end
63 end 113 end
64 114
65 def assert_query_statement_includes(query, condition) 115 def assert_query_statement_includes(query, condition)
66 assert query.statement.include?(condition), "Query statement condition not found in: #{query.statement}" 116 assert_include condition, query.statement
67 end 117 end
68 118
69 def assert_query_result(expected, query) 119 def assert_query_result(expected, query)
70 assert_nothing_raised do 120 assert_nothing_raised do
71 assert_equal expected.map(&:id).sort, query.issues.map(&:id).sort 121 assert_equal expected.map(&:id).sort, query.issues.map(&:id).sort
72 assert_equal expected.size, query.issue_count 122 assert_equal expected.size, query.issue_count
73 end 123 end
74 end 124 end
75 125
76 def test_query_should_allow_shared_versions_for_a_project_query 126 def test_query_should_allow_shared_versions_for_a_project_query
77 subproject_version = Version.find(4) 127 subproject_version = Version.find(4)
78 query = Query.new(:project => Project.find(1), :name => '_') 128 query = IssueQuery.new(:project => Project.find(1), :name => '_')
79 query.add_filter('fixed_version_id', '=', [subproject_version.id.to_s]) 129 query.add_filter('fixed_version_id', '=', [subproject_version.id.to_s])
80 130
81 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IN ('4')") 131 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IN ('4')")
82 end 132 end
83 133
84 def test_query_with_multiple_custom_fields 134 def test_query_with_multiple_custom_fields
85 query = Query.find(1) 135 query = IssueQuery.find(1)
86 assert query.valid? 136 assert query.valid?
87 assert query.statement.include?("#{CustomValue.table_name}.value IN ('MySQL')") 137 assert query.statement.include?("#{CustomValue.table_name}.value IN ('MySQL')")
88 issues = find_issues_with_query(query) 138 issues = find_issues_with_query(query)
89 assert_equal 1, issues.length 139 assert_equal 1, issues.length
90 assert_equal Issue.find(3), issues.first 140 assert_equal Issue.find(3), issues.first
91 end 141 end
92 142
93 def test_operator_none 143 def test_operator_none
94 query = Query.new(:project => Project.find(1), :name => '_') 144 query = IssueQuery.new(:project => Project.find(1), :name => '_')
95 query.add_filter('fixed_version_id', '!*', ['']) 145 query.add_filter('fixed_version_id', '!*', [''])
96 query.add_filter('cf_1', '!*', ['']) 146 query.add_filter('cf_1', '!*', [''])
97 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NULL") 147 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NULL")
98 assert query.statement.include?("#{CustomValue.table_name}.value IS NULL OR #{CustomValue.table_name}.value = ''") 148 assert query.statement.include?("#{CustomValue.table_name}.value IS NULL OR #{CustomValue.table_name}.value = ''")
99 find_issues_with_query(query) 149 find_issues_with_query(query)
100 end 150 end
101 151
102 def test_operator_none_for_integer 152 def test_operator_none_for_integer
103 query = Query.new(:project => Project.find(1), :name => '_') 153 query = IssueQuery.new(:project => Project.find(1), :name => '_')
104 query.add_filter('estimated_hours', '!*', ['']) 154 query.add_filter('estimated_hours', '!*', [''])
105 issues = find_issues_with_query(query) 155 issues = find_issues_with_query(query)
106 assert !issues.empty? 156 assert !issues.empty?
107 assert issues.all? {|i| !i.estimated_hours} 157 assert issues.all? {|i| !i.estimated_hours}
108 end 158 end
109 159
110 def test_operator_none_for_date 160 def test_operator_none_for_date
111 query = Query.new(:project => Project.find(1), :name => '_') 161 query = IssueQuery.new(:project => Project.find(1), :name => '_')
112 query.add_filter('start_date', '!*', ['']) 162 query.add_filter('start_date', '!*', [''])
113 issues = find_issues_with_query(query) 163 issues = find_issues_with_query(query)
114 assert !issues.empty? 164 assert !issues.empty?
115 assert issues.all? {|i| i.start_date.nil?} 165 assert issues.all? {|i| i.start_date.nil?}
116 end 166 end
117 167
118 def test_operator_none_for_string_custom_field 168 def test_operator_none_for_string_custom_field
119 query = Query.new(:project => Project.find(1), :name => '_') 169 query = IssueQuery.new(:project => Project.find(1), :name => '_')
120 query.add_filter('cf_2', '!*', ['']) 170 query.add_filter('cf_2', '!*', [''])
121 assert query.has_filter?('cf_2') 171 assert query.has_filter?('cf_2')
122 issues = find_issues_with_query(query) 172 issues = find_issues_with_query(query)
123 assert !issues.empty? 173 assert !issues.empty?
124 assert issues.all? {|i| i.custom_field_value(2).blank?} 174 assert issues.all? {|i| i.custom_field_value(2).blank?}
125 end 175 end
126 176
127 def test_operator_all 177 def test_operator_all
128 query = Query.new(:project => Project.find(1), :name => '_') 178 query = IssueQuery.new(:project => Project.find(1), :name => '_')
129 query.add_filter('fixed_version_id', '*', ['']) 179 query.add_filter('fixed_version_id', '*', [''])
130 query.add_filter('cf_1', '*', ['']) 180 query.add_filter('cf_1', '*', [''])
131 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NOT NULL") 181 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NOT NULL")
132 assert query.statement.include?("#{CustomValue.table_name}.value IS NOT NULL AND #{CustomValue.table_name}.value <> ''") 182 assert query.statement.include?("#{CustomValue.table_name}.value IS NOT NULL AND #{CustomValue.table_name}.value <> ''")
133 find_issues_with_query(query) 183 find_issues_with_query(query)
134 end 184 end
135 185
136 def test_operator_all_for_date 186 def test_operator_all_for_date
137 query = Query.new(:project => Project.find(1), :name => '_') 187 query = IssueQuery.new(:project => Project.find(1), :name => '_')
138 query.add_filter('start_date', '*', ['']) 188 query.add_filter('start_date', '*', [''])
139 issues = find_issues_with_query(query) 189 issues = find_issues_with_query(query)
140 assert !issues.empty? 190 assert !issues.empty?
141 assert issues.all? {|i| i.start_date.present?} 191 assert issues.all? {|i| i.start_date.present?}
142 end 192 end
143 193
144 def test_operator_all_for_string_custom_field 194 def test_operator_all_for_string_custom_field
145 query = Query.new(:project => Project.find(1), :name => '_') 195 query = IssueQuery.new(:project => Project.find(1), :name => '_')
146 query.add_filter('cf_2', '*', ['']) 196 query.add_filter('cf_2', '*', [''])
147 assert query.has_filter?('cf_2') 197 assert query.has_filter?('cf_2')
148 issues = find_issues_with_query(query) 198 issues = find_issues_with_query(query)
149 assert !issues.empty? 199 assert !issues.empty?
150 assert issues.all? {|i| i.custom_field_value(2).present?} 200 assert issues.all? {|i| i.custom_field_value(2).present?}
151 end 201 end
152 202
153 def test_numeric_filter_should_not_accept_non_numeric_values 203 def test_numeric_filter_should_not_accept_non_numeric_values
154 query = Query.new(:name => '_') 204 query = IssueQuery.new(:name => '_')
155 query.add_filter('estimated_hours', '=', ['a']) 205 query.add_filter('estimated_hours', '=', ['a'])
156 206
157 assert query.has_filter?('estimated_hours') 207 assert query.has_filter?('estimated_hours')
158 assert !query.valid? 208 assert !query.valid?
159 end 209 end
160 210
161 def test_operator_is_on_float 211 def test_operator_is_on_float
162 Issue.update_all("estimated_hours = 171.2", "id=2") 212 Issue.where(:id => 2).update_all("estimated_hours = 171.2")
163 213 query = IssueQuery.new(:name => '_')
164 query = Query.new(:name => '_')
165 query.add_filter('estimated_hours', '=', ['171.20']) 214 query.add_filter('estimated_hours', '=', ['171.20'])
166 issues = find_issues_with_query(query) 215 issues = find_issues_with_query(query)
167 assert_equal 1, issues.size 216 assert_equal 1, issues.size
168 assert_equal 2, issues.first.id 217 assert_equal 2, issues.first.id
169 end 218 end
170 219
171 def test_operator_is_on_integer_custom_field 220 def test_operator_is_on_integer_custom_field
172 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true) 221 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true, :trackers => Tracker.all)
173 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7') 222 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
174 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12') 223 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12')
175 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '') 224 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
176 225
177 query = Query.new(:name => '_') 226 query = IssueQuery.new(:name => '_')
178 query.add_filter("cf_#{f.id}", '=', ['12']) 227 query.add_filter("cf_#{f.id}", '=', ['12'])
179 issues = find_issues_with_query(query) 228 issues = find_issues_with_query(query)
180 assert_equal 1, issues.size 229 assert_equal 1, issues.size
181 assert_equal 2, issues.first.id 230 assert_equal 2, issues.first.id
182 end 231 end
183 232
184 def test_operator_is_on_integer_custom_field_should_accept_negative_value 233 def test_operator_is_on_integer_custom_field_should_accept_negative_value
185 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true) 234 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true, :trackers => Tracker.all)
186 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7') 235 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
187 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12') 236 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12')
188 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '') 237 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
189 238
190 query = Query.new(:name => '_') 239 query = IssueQuery.new(:name => '_')
191 query.add_filter("cf_#{f.id}", '=', ['-12']) 240 query.add_filter("cf_#{f.id}", '=', ['-12'])
192 assert query.valid? 241 assert query.valid?
193 issues = find_issues_with_query(query) 242 issues = find_issues_with_query(query)
194 assert_equal 1, issues.size 243 assert_equal 1, issues.size
195 assert_equal 2, issues.first.id 244 assert_equal 2, issues.first.id
196 end 245 end
197 246
198 def test_operator_is_on_float_custom_field 247 def test_operator_is_on_float_custom_field
199 f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true) 248 f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
200 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3') 249 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3')
201 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12.7') 250 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12.7')
202 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '') 251 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
203 252
204 query = Query.new(:name => '_') 253 query = IssueQuery.new(:name => '_')
205 query.add_filter("cf_#{f.id}", '=', ['12.7']) 254 query.add_filter("cf_#{f.id}", '=', ['12.7'])
206 issues = find_issues_with_query(query) 255 issues = find_issues_with_query(query)
207 assert_equal 1, issues.size 256 assert_equal 1, issues.size
208 assert_equal 2, issues.first.id 257 assert_equal 2, issues.first.id
209 end 258 end
210 259
211 def test_operator_is_on_float_custom_field_should_accept_negative_value 260 def test_operator_is_on_float_custom_field_should_accept_negative_value
212 f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true) 261 f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
213 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3') 262 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3')
214 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12.7') 263 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12.7')
215 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '') 264 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
216 265
217 query = Query.new(:name => '_') 266 query = IssueQuery.new(:name => '_')
218 query.add_filter("cf_#{f.id}", '=', ['-12.7']) 267 query.add_filter("cf_#{f.id}", '=', ['-12.7'])
219 assert query.valid? 268 assert query.valid?
220 issues = find_issues_with_query(query) 269 issues = find_issues_with_query(query)
221 assert_equal 1, issues.size 270 assert_equal 1, issues.size
222 assert_equal 2, issues.first.id 271 assert_equal 2, issues.first.id
223 end 272 end
224 273
225 def test_operator_is_on_multi_list_custom_field 274 def test_operator_is_on_multi_list_custom_field
226 f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true, 275 f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
227 :possible_values => ['value1', 'value2', 'value3'], :multiple => true) 276 :possible_values => ['value1', 'value2', 'value3'], :multiple => true, :trackers => Tracker.all)
228 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1') 277 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1')
229 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2') 278 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2')
230 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1') 279 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1')
231 280
232 query = Query.new(:name => '_') 281 query = IssueQuery.new(:name => '_')
233 query.add_filter("cf_#{f.id}", '=', ['value1']) 282 query.add_filter("cf_#{f.id}", '=', ['value1'])
234 issues = find_issues_with_query(query) 283 issues = find_issues_with_query(query)
235 assert_equal [1, 3], issues.map(&:id).sort 284 assert_equal [1, 3], issues.map(&:id).sort
236 285
237 query = Query.new(:name => '_') 286 query = IssueQuery.new(:name => '_')
238 query.add_filter("cf_#{f.id}", '=', ['value2']) 287 query.add_filter("cf_#{f.id}", '=', ['value2'])
239 issues = find_issues_with_query(query) 288 issues = find_issues_with_query(query)
240 assert_equal [1], issues.map(&:id).sort 289 assert_equal [1], issues.map(&:id).sort
241 end 290 end
242 291
243 def test_operator_is_not_on_multi_list_custom_field 292 def test_operator_is_not_on_multi_list_custom_field
244 f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true, 293 f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
245 :possible_values => ['value1', 'value2', 'value3'], :multiple => true) 294 :possible_values => ['value1', 'value2', 'value3'], :multiple => true, :trackers => Tracker.all)
246 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1') 295 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1')
247 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2') 296 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2')
248 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1') 297 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1')
249 298
250 query = Query.new(:name => '_') 299 query = IssueQuery.new(:name => '_')
251 query.add_filter("cf_#{f.id}", '!', ['value1']) 300 query.add_filter("cf_#{f.id}", '!', ['value1'])
252 issues = find_issues_with_query(query) 301 issues = find_issues_with_query(query)
253 assert !issues.map(&:id).include?(1) 302 assert !issues.map(&:id).include?(1)
254 assert !issues.map(&:id).include?(3) 303 assert !issues.map(&:id).include?(3)
255 304
256 query = Query.new(:name => '_') 305 query = IssueQuery.new(:name => '_')
257 query.add_filter("cf_#{f.id}", '!', ['value2']) 306 query.add_filter("cf_#{f.id}", '!', ['value2'])
258 issues = find_issues_with_query(query) 307 issues = find_issues_with_query(query)
259 assert !issues.map(&:id).include?(1) 308 assert !issues.map(&:id).include?(1)
260 assert issues.map(&:id).include?(3) 309 assert issues.map(&:id).include?(3)
261 end 310 end
262 311
263 def test_operator_is_on_is_private_field 312 def test_operator_is_on_is_private_field
264 # is_private filter only available for those who can set issues private 313 # is_private filter only available for those who can set issues private
265 User.current = User.find(2) 314 User.current = User.find(2)
266 315
267 query = Query.new(:name => '_') 316 query = IssueQuery.new(:name => '_')
268 assert query.available_filters.key?('is_private') 317 assert query.available_filters.key?('is_private')
269 318
270 query.add_filter("is_private", '=', ['1']) 319 query.add_filter("is_private", '=', ['1'])
271 issues = find_issues_with_query(query) 320 issues = find_issues_with_query(query)
272 assert issues.any? 321 assert issues.any?
277 326
278 def test_operator_is_not_on_is_private_field 327 def test_operator_is_not_on_is_private_field
279 # is_private filter only available for those who can set issues private 328 # is_private filter only available for those who can set issues private
280 User.current = User.find(2) 329 User.current = User.find(2)
281 330
282 query = Query.new(:name => '_') 331 query = IssueQuery.new(:name => '_')
283 assert query.available_filters.key?('is_private') 332 assert query.available_filters.key?('is_private')
284 333
285 query.add_filter("is_private", '!', ['1']) 334 query.add_filter("is_private", '!', ['1'])
286 issues = find_issues_with_query(query) 335 issues = find_issues_with_query(query)
287 assert issues.any? 336 assert issues.any?
289 ensure 338 ensure
290 User.current = nil 339 User.current = nil
291 end 340 end
292 341
293 def test_operator_greater_than 342 def test_operator_greater_than
294 query = Query.new(:project => Project.find(1), :name => '_') 343 query = IssueQuery.new(:project => Project.find(1), :name => '_')
295 query.add_filter('done_ratio', '>=', ['40']) 344 query.add_filter('done_ratio', '>=', ['40'])
296 assert query.statement.include?("#{Issue.table_name}.done_ratio >= 40.0") 345 assert query.statement.include?("#{Issue.table_name}.done_ratio >= 40.0")
297 find_issues_with_query(query) 346 find_issues_with_query(query)
298 end 347 end
299 348
300 def test_operator_greater_than_a_float 349 def test_operator_greater_than_a_float
301 query = Query.new(:project => Project.find(1), :name => '_') 350 query = IssueQuery.new(:project => Project.find(1), :name => '_')
302 query.add_filter('estimated_hours', '>=', ['40.5']) 351 query.add_filter('estimated_hours', '>=', ['40.5'])
303 assert query.statement.include?("#{Issue.table_name}.estimated_hours >= 40.5") 352 assert query.statement.include?("#{Issue.table_name}.estimated_hours >= 40.5")
304 find_issues_with_query(query) 353 find_issues_with_query(query)
305 end 354 end
306 355
307 def test_operator_greater_than_on_int_custom_field 356 def test_operator_greater_than_on_int_custom_field
308 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true) 357 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
309 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7') 358 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
310 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12') 359 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12')
311 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '') 360 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
312 361
313 query = Query.new(:project => Project.find(1), :name => '_') 362 query = IssueQuery.new(:project => Project.find(1), :name => '_')
314 query.add_filter("cf_#{f.id}", '>=', ['8']) 363 query.add_filter("cf_#{f.id}", '>=', ['8'])
315 issues = find_issues_with_query(query) 364 issues = find_issues_with_query(query)
316 assert_equal 1, issues.size 365 assert_equal 1, issues.size
317 assert_equal 2, issues.first.id 366 assert_equal 2, issues.first.id
318 end 367 end
319 368
320 def test_operator_lesser_than 369 def test_operator_lesser_than
321 query = Query.new(:project => Project.find(1), :name => '_') 370 query = IssueQuery.new(:project => Project.find(1), :name => '_')
322 query.add_filter('done_ratio', '<=', ['30']) 371 query.add_filter('done_ratio', '<=', ['30'])
323 assert query.statement.include?("#{Issue.table_name}.done_ratio <= 30.0") 372 assert query.statement.include?("#{Issue.table_name}.done_ratio <= 30.0")
324 find_issues_with_query(query) 373 find_issues_with_query(query)
325 end 374 end
326 375
327 def test_operator_lesser_than_on_custom_field 376 def test_operator_lesser_than_on_custom_field
328 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true) 377 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
329 query = Query.new(:project => Project.find(1), :name => '_') 378 query = IssueQuery.new(:project => Project.find(1), :name => '_')
330 query.add_filter("cf_#{f.id}", '<=', ['30']) 379 query.add_filter("cf_#{f.id}", '<=', ['30'])
331 assert query.statement.include?("CAST(custom_values.value AS decimal(60,3)) <= 30.0") 380 assert_match /CAST.+ <= 30\.0/, query.statement
332 find_issues_with_query(query) 381 find_issues_with_query(query)
382 end
383
384 def test_operator_lesser_than_on_date_custom_field
385 f = IssueCustomField.create!(:name => 'filter', :field_format => 'date', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
386 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '2013-04-11')
387 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '2013-05-14')
388 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
389
390 query = IssueQuery.new(:project => Project.find(1), :name => '_')
391 query.add_filter("cf_#{f.id}", '<=', ['2013-05-01'])
392 issue_ids = find_issues_with_query(query).map(&:id)
393 assert_include 1, issue_ids
394 assert_not_include 2, issue_ids
395 assert_not_include 3, issue_ids
333 end 396 end
334 397
335 def test_operator_between 398 def test_operator_between
336 query = Query.new(:project => Project.find(1), :name => '_') 399 query = IssueQuery.new(:project => Project.find(1), :name => '_')
337 query.add_filter('done_ratio', '><', ['30', '40']) 400 query.add_filter('done_ratio', '><', ['30', '40'])
338 assert_include "#{Issue.table_name}.done_ratio BETWEEN 30.0 AND 40.0", query.statement 401 assert_include "#{Issue.table_name}.done_ratio BETWEEN 30.0 AND 40.0", query.statement
339 find_issues_with_query(query) 402 find_issues_with_query(query)
340 end 403 end
341 404
342 def test_operator_between_on_custom_field 405 def test_operator_between_on_custom_field
343 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true) 406 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
344 query = Query.new(:project => Project.find(1), :name => '_') 407 query = IssueQuery.new(:project => Project.find(1), :name => '_')
345 query.add_filter("cf_#{f.id}", '><', ['30', '40']) 408 query.add_filter("cf_#{f.id}", '><', ['30', '40'])
346 assert_include "CAST(custom_values.value AS decimal(60,3)) BETWEEN 30.0 AND 40.0", query.statement 409 assert_match /CAST.+ BETWEEN 30.0 AND 40.0/, query.statement
347 find_issues_with_query(query) 410 find_issues_with_query(query)
348 end 411 end
349 412
350 def test_date_filter_should_not_accept_non_date_values 413 def test_date_filter_should_not_accept_non_date_values
351 query = Query.new(:name => '_') 414 query = IssueQuery.new(:name => '_')
352 query.add_filter('created_on', '=', ['a']) 415 query.add_filter('created_on', '=', ['a'])
353 416
354 assert query.has_filter?('created_on') 417 assert query.has_filter?('created_on')
355 assert !query.valid? 418 assert !query.valid?
356 end 419 end
357 420
358 def test_date_filter_should_not_accept_invalid_date_values 421 def test_date_filter_should_not_accept_invalid_date_values
359 query = Query.new(:name => '_') 422 query = IssueQuery.new(:name => '_')
360 query.add_filter('created_on', '=', ['2011-01-34']) 423 query.add_filter('created_on', '=', ['2011-01-34'])
361 424
362 assert query.has_filter?('created_on') 425 assert query.has_filter?('created_on')
363 assert !query.valid? 426 assert !query.valid?
364 end 427 end
365 428
366 def test_relative_date_filter_should_not_accept_non_integer_values 429 def test_relative_date_filter_should_not_accept_non_integer_values
367 query = Query.new(:name => '_') 430 query = IssueQuery.new(:name => '_')
368 query.add_filter('created_on', '>t-', ['a']) 431 query.add_filter('created_on', '>t-', ['a'])
369 432
370 assert query.has_filter?('created_on') 433 assert query.has_filter?('created_on')
371 assert !query.valid? 434 assert !query.valid?
372 end 435 end
373 436
374 def test_operator_date_equals 437 def test_operator_date_equals
375 query = Query.new(:name => '_') 438 query = IssueQuery.new(:name => '_')
376 query.add_filter('due_date', '=', ['2011-07-10']) 439 query.add_filter('due_date', '=', ['2011-07-10'])
377 assert_match /issues\.due_date > '2011-07-09 23:59:59(\.9+)?' AND issues\.due_date <= '2011-07-10 23:59:59(\.9+)?/, query.statement 440 assert_match /issues\.due_date > '2011-07-09 23:59:59(\.9+)?' AND issues\.due_date <= '2011-07-10 23:59:59(\.9+)?/, query.statement
378 find_issues_with_query(query) 441 find_issues_with_query(query)
379 end 442 end
380 443
381 def test_operator_date_lesser_than 444 def test_operator_date_lesser_than
382 query = Query.new(:name => '_') 445 query = IssueQuery.new(:name => '_')
383 query.add_filter('due_date', '<=', ['2011-07-10']) 446 query.add_filter('due_date', '<=', ['2011-07-10'])
384 assert_match /issues\.due_date <= '2011-07-10 23:59:59(\.9+)?/, query.statement 447 assert_match /issues\.due_date <= '2011-07-10 23:59:59(\.9+)?/, query.statement
385 find_issues_with_query(query) 448 find_issues_with_query(query)
386 end 449 end
387 450
451 def test_operator_date_lesser_than_with_timestamp
452 query = IssueQuery.new(:name => '_')
453 query.add_filter('updated_on', '<=', ['2011-07-10T19:13:52'])
454 assert_match /issues\.updated_on <= '2011-07-10 19:13:52/, query.statement
455 find_issues_with_query(query)
456 end
457
388 def test_operator_date_greater_than 458 def test_operator_date_greater_than
389 query = Query.new(:name => '_') 459 query = IssueQuery.new(:name => '_')
390 query.add_filter('due_date', '>=', ['2011-07-10']) 460 query.add_filter('due_date', '>=', ['2011-07-10'])
391 assert_match /issues\.due_date > '2011-07-09 23:59:59(\.9+)?'/, query.statement 461 assert_match /issues\.due_date > '2011-07-09 23:59:59(\.9+)?'/, query.statement
392 find_issues_with_query(query) 462 find_issues_with_query(query)
393 end 463 end
394 464
465 def test_operator_date_greater_than_with_timestamp
466 query = IssueQuery.new(:name => '_')
467 query.add_filter('updated_on', '>=', ['2011-07-10T19:13:52'])
468 assert_match /issues\.updated_on > '2011-07-10 19:13:51(\.0+)?'/, query.statement
469 find_issues_with_query(query)
470 end
471
395 def test_operator_date_between 472 def test_operator_date_between
396 query = Query.new(:name => '_') 473 query = IssueQuery.new(:name => '_')
397 query.add_filter('due_date', '><', ['2011-06-23', '2011-07-10']) 474 query.add_filter('due_date', '><', ['2011-06-23', '2011-07-10'])
398 assert_match /issues\.due_date > '2011-06-22 23:59:59(\.9+)?' AND issues\.due_date <= '2011-07-10 23:59:59(\.9+)?/, query.statement 475 assert_match /issues\.due_date > '2011-06-22 23:59:59(\.9+)?' AND issues\.due_date <= '2011-07-10 23:59:59(\.9+)?'/, query.statement
399 find_issues_with_query(query) 476 find_issues_with_query(query)
400 end 477 end
401 478
402 def test_operator_in_more_than 479 def test_operator_in_more_than
403 Issue.find(7).update_attribute(:due_date, (Date.today + 15)) 480 Issue.find(7).update_attribute(:due_date, (Date.today + 15))
404 query = Query.new(:project => Project.find(1), :name => '_') 481 query = IssueQuery.new(:project => Project.find(1), :name => '_')
405 query.add_filter('due_date', '>t+', ['15']) 482 query.add_filter('due_date', '>t+', ['15'])
406 issues = find_issues_with_query(query) 483 issues = find_issues_with_query(query)
407 assert !issues.empty? 484 assert !issues.empty?
408 issues.each {|issue| assert(issue.due_date >= (Date.today + 15))} 485 issues.each {|issue| assert(issue.due_date >= (Date.today + 15))}
409 end 486 end
410 487
411 def test_operator_in_less_than 488 def test_operator_in_less_than
412 query = Query.new(:project => Project.find(1), :name => '_') 489 query = IssueQuery.new(:project => Project.find(1), :name => '_')
413 query.add_filter('due_date', '<t+', ['15']) 490 query.add_filter('due_date', '<t+', ['15'])
414 issues = find_issues_with_query(query) 491 issues = find_issues_with_query(query)
415 assert !issues.empty? 492 assert !issues.empty?
416 issues.each {|issue| assert(issue.due_date <= (Date.today + 15))} 493 issues.each {|issue| assert(issue.due_date <= (Date.today + 15))}
417 end 494 end
418 495
419 def test_operator_in_the_next_days 496 def test_operator_in_the_next_days
420 query = Query.new(:project => Project.find(1), :name => '_') 497 query = IssueQuery.new(:project => Project.find(1), :name => '_')
421 query.add_filter('due_date', '><t+', ['15']) 498 query.add_filter('due_date', '><t+', ['15'])
422 issues = find_issues_with_query(query) 499 issues = find_issues_with_query(query)
423 assert !issues.empty? 500 assert !issues.empty?
424 issues.each {|issue| assert(issue.due_date >= Date.today && issue.due_date <= (Date.today + 15))} 501 issues.each {|issue| assert(issue.due_date >= Date.today && issue.due_date <= (Date.today + 15))}
425 end 502 end
426 503
427 def test_operator_less_than_ago 504 def test_operator_less_than_ago
428 Issue.find(7).update_attribute(:due_date, (Date.today - 3)) 505 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
429 query = Query.new(:project => Project.find(1), :name => '_') 506 query = IssueQuery.new(:project => Project.find(1), :name => '_')
430 query.add_filter('due_date', '>t-', ['3']) 507 query.add_filter('due_date', '>t-', ['3'])
431 issues = find_issues_with_query(query) 508 issues = find_issues_with_query(query)
432 assert !issues.empty? 509 assert !issues.empty?
433 issues.each {|issue| assert(issue.due_date >= (Date.today - 3))} 510 issues.each {|issue| assert(issue.due_date >= (Date.today - 3))}
434 end 511 end
435 512
436 def test_operator_in_the_past_days 513 def test_operator_in_the_past_days
437 Issue.find(7).update_attribute(:due_date, (Date.today - 3)) 514 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
438 query = Query.new(:project => Project.find(1), :name => '_') 515 query = IssueQuery.new(:project => Project.find(1), :name => '_')
439 query.add_filter('due_date', '><t-', ['3']) 516 query.add_filter('due_date', '><t-', ['3'])
440 issues = find_issues_with_query(query) 517 issues = find_issues_with_query(query)
441 assert !issues.empty? 518 assert !issues.empty?
442 issues.each {|issue| assert(issue.due_date >= (Date.today - 3) && issue.due_date <= Date.today)} 519 issues.each {|issue| assert(issue.due_date >= (Date.today - 3) && issue.due_date <= Date.today)}
443 end 520 end
444 521
445 def test_operator_more_than_ago 522 def test_operator_more_than_ago
446 Issue.find(7).update_attribute(:due_date, (Date.today - 10)) 523 Issue.find(7).update_attribute(:due_date, (Date.today - 10))
447 query = Query.new(:project => Project.find(1), :name => '_') 524 query = IssueQuery.new(:project => Project.find(1), :name => '_')
448 query.add_filter('due_date', '<t-', ['10']) 525 query.add_filter('due_date', '<t-', ['10'])
449 assert query.statement.include?("#{Issue.table_name}.due_date <=") 526 assert query.statement.include?("#{Issue.table_name}.due_date <=")
450 issues = find_issues_with_query(query) 527 issues = find_issues_with_query(query)
451 assert !issues.empty? 528 assert !issues.empty?
452 issues.each {|issue| assert(issue.due_date <= (Date.today - 10))} 529 issues.each {|issue| assert(issue.due_date <= (Date.today - 10))}
453 end 530 end
454 531
455 def test_operator_in 532 def test_operator_in
456 Issue.find(7).update_attribute(:due_date, (Date.today + 2)) 533 Issue.find(7).update_attribute(:due_date, (Date.today + 2))
457 query = Query.new(:project => Project.find(1), :name => '_') 534 query = IssueQuery.new(:project => Project.find(1), :name => '_')
458 query.add_filter('due_date', 't+', ['2']) 535 query.add_filter('due_date', 't+', ['2'])
459 issues = find_issues_with_query(query) 536 issues = find_issues_with_query(query)
460 assert !issues.empty? 537 assert !issues.empty?
461 issues.each {|issue| assert_equal((Date.today + 2), issue.due_date)} 538 issues.each {|issue| assert_equal((Date.today + 2), issue.due_date)}
462 end 539 end
463 540
464 def test_operator_ago 541 def test_operator_ago
465 Issue.find(7).update_attribute(:due_date, (Date.today - 3)) 542 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
466 query = Query.new(:project => Project.find(1), :name => '_') 543 query = IssueQuery.new(:project => Project.find(1), :name => '_')
467 query.add_filter('due_date', 't-', ['3']) 544 query.add_filter('due_date', 't-', ['3'])
468 issues = find_issues_with_query(query) 545 issues = find_issues_with_query(query)
469 assert !issues.empty? 546 assert !issues.empty?
470 issues.each {|issue| assert_equal((Date.today - 3), issue.due_date)} 547 issues.each {|issue| assert_equal((Date.today - 3), issue.due_date)}
471 end 548 end
472 549
473 def test_operator_today 550 def test_operator_today
474 query = Query.new(:project => Project.find(1), :name => '_') 551 query = IssueQuery.new(:project => Project.find(1), :name => '_')
475 query.add_filter('due_date', 't', ['']) 552 query.add_filter('due_date', 't', [''])
476 issues = find_issues_with_query(query) 553 issues = find_issues_with_query(query)
477 assert !issues.empty? 554 assert !issues.empty?
478 issues.each {|issue| assert_equal Date.today, issue.due_date} 555 issues.each {|issue| assert_equal Date.today, issue.due_date}
479 end 556 end
480 557
481 def test_operator_this_week_on_date 558 def test_operator_this_week_on_date
482 query = Query.new(:project => Project.find(1), :name => '_') 559 query = IssueQuery.new(:project => Project.find(1), :name => '_')
483 query.add_filter('due_date', 'w', ['']) 560 query.add_filter('due_date', 'w', [''])
484 find_issues_with_query(query) 561 find_issues_with_query(query)
485 end 562 end
486 563
487 def test_operator_this_week_on_datetime 564 def test_operator_this_week_on_datetime
488 query = Query.new(:project => Project.find(1), :name => '_') 565 query = IssueQuery.new(:project => Project.find(1), :name => '_')
489 query.add_filter('created_on', 'w', ['']) 566 query.add_filter('created_on', 'w', [''])
490 find_issues_with_query(query) 567 find_issues_with_query(query)
491 end 568 end
492 569
493 def test_operator_contains 570 def test_operator_contains
494 query = Query.new(:project => Project.find(1), :name => '_') 571 query = IssueQuery.new(:project => Project.find(1), :name => '_')
495 query.add_filter('subject', '~', ['uNable']) 572 query.add_filter('subject', '~', ['uNable'])
496 assert query.statement.include?("LOWER(#{Issue.table_name}.subject) LIKE '%unable%'") 573 assert query.statement.include?("LOWER(#{Issue.table_name}.subject) LIKE '%unable%'")
497 result = find_issues_with_query(query) 574 result = find_issues_with_query(query)
498 assert result.empty? 575 assert result.empty?
499 result.each {|issue| assert issue.subject.downcase.include?('unable') } 576 result.each {|issue| assert issue.subject.downcase.include?('unable') }
503 I18n.locale = :fr 580 I18n.locale = :fr
504 assert_equal '1', I18n.t(:general_first_day_of_week) 581 assert_equal '1', I18n.t(:general_first_day_of_week)
505 582
506 Date.stubs(:today).returns(Date.parse('2011-04-29')) 583 Date.stubs(:today).returns(Date.parse('2011-04-29'))
507 584
508 query = Query.new(:project => Project.find(1), :name => '_') 585 query = IssueQuery.new(:project => Project.find(1), :name => '_')
509 query.add_filter('due_date', 'w', ['']) 586 query.add_filter('due_date', 'w', [''])
510 assert query.statement.match(/issues\.due_date > '2011-04-24 23:59:59(\.9+)?' AND issues\.due_date <= '2011-05-01 23:59:59(\.9+)?/), "range not found in #{query.statement}" 587 assert query.statement.match(/issues\.due_date > '2011-04-24 23:59:59(\.9+)?' AND issues\.due_date <= '2011-05-01 23:59:59(\.9+)?/), "range not found in #{query.statement}"
511 I18n.locale = :en 588 I18n.locale = :en
512 end 589 end
513 590
515 I18n.locale = :en 592 I18n.locale = :en
516 assert_equal '7', I18n.t(:general_first_day_of_week) 593 assert_equal '7', I18n.t(:general_first_day_of_week)
517 594
518 Date.stubs(:today).returns(Date.parse('2011-04-29')) 595 Date.stubs(:today).returns(Date.parse('2011-04-29'))
519 596
520 query = Query.new(:project => Project.find(1), :name => '_') 597 query = IssueQuery.new(:project => Project.find(1), :name => '_')
521 query.add_filter('due_date', 'w', ['']) 598 query.add_filter('due_date', 'w', [''])
522 assert query.statement.match(/issues\.due_date > '2011-04-23 23:59:59(\.9+)?' AND issues\.due_date <= '2011-04-30 23:59:59(\.9+)?/), "range not found in #{query.statement}" 599 assert query.statement.match(/issues\.due_date > '2011-04-23 23:59:59(\.9+)?' AND issues\.due_date <= '2011-04-30 23:59:59(\.9+)?/), "range not found in #{query.statement}"
523 end 600 end
524 601
525 def test_operator_does_not_contains 602 def test_operator_does_not_contains
526 query = Query.new(:project => Project.find(1), :name => '_') 603 query = IssueQuery.new(:project => Project.find(1), :name => '_')
527 query.add_filter('subject', '!~', ['uNable']) 604 query.add_filter('subject', '!~', ['uNable'])
528 assert query.statement.include?("LOWER(#{Issue.table_name}.subject) NOT LIKE '%unable%'") 605 assert query.statement.include?("LOWER(#{Issue.table_name}.subject) NOT LIKE '%unable%'")
529 find_issues_with_query(query) 606 find_issues_with_query(query)
530 end 607 end
531 608
536 i1 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => user) 613 i1 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => user)
537 i2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => group) 614 i2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => group)
538 i3 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => Group.find(11)) 615 i3 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => Group.find(11))
539 group.users << user 616 group.users << user
540 617
541 query = Query.new(:name => '_', :filters => { 'assigned_to_id' => {:operator => '=', :values => ['me']}}) 618 query = IssueQuery.new(:name => '_', :filters => { 'assigned_to_id' => {:operator => '=', :values => ['me']}})
542 result = query.issues 619 result = query.issues
543 assert_equal Issue.visible.all(:conditions => {:assigned_to_id => ([2] + user.reload.group_ids)}).sort_by(&:id), result.sort_by(&:id) 620 assert_equal Issue.visible.where(:assigned_to_id => ([2] + user.reload.group_ids)).sort_by(&:id), result.sort_by(&:id)
544 621
545 assert result.include?(i1) 622 assert result.include?(i1)
546 assert result.include?(i2) 623 assert result.include?(i2)
547 assert !result.include?(i3) 624 assert !result.include?(i3)
548 end 625 end
551 User.current = User.find(2) 628 User.current = User.find(2)
552 cf = IssueCustomField.create!(:field_format => 'user', :is_for_all => true, :is_filter => true, :name => 'User custom field', :tracker_ids => [1]) 629 cf = IssueCustomField.create!(:field_format => 'user', :is_for_all => true, :is_filter => true, :name => 'User custom field', :tracker_ids => [1])
553 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '2'}, :subject => 'Test', :author_id => 1) 630 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '2'}, :subject => 'Test', :author_id => 1)
554 issue2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '3'}) 631 issue2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '3'})
555 632
556 query = Query.new(:name => '_', :project => Project.find(1)) 633 query = IssueQuery.new(:name => '_', :project => Project.find(1))
557 filter = query.available_filters["cf_#{cf.id}"] 634 filter = query.available_filters["cf_#{cf.id}"]
558 assert_not_nil filter 635 assert_not_nil filter
559 assert_include 'me', filter[:values].map{|v| v[1]} 636 assert_include 'me', filter[:values].map{|v| v[1]}
560 637
561 query.filters = { "cf_#{cf.id}" => {:operator => '=', :values => ['me']}} 638 query.filters = { "cf_#{cf.id}" => {:operator => '=', :values => ['me']}}
564 assert_equal issue1, result.first 641 assert_equal issue1, result.first
565 end 642 end
566 643
567 def test_filter_my_projects 644 def test_filter_my_projects
568 User.current = User.find(2) 645 User.current = User.find(2)
569 query = Query.new(:name => '_') 646 query = IssueQuery.new(:name => '_')
570 filter = query.available_filters['project_id'] 647 filter = query.available_filters['project_id']
571 assert_not_nil filter 648 assert_not_nil filter
572 assert_include 'mine', filter[:values].map{|v| v[1]} 649 assert_include 'mine', filter[:values].map{|v| v[1]}
573 650
574 query.filters = { 'project_id' => {:operator => '=', :values => ['mine']}} 651 query.filters = { 'project_id' => {:operator => '=', :values => ['mine']}}
576 assert_nil result.detect {|issue| !User.current.member_of?(issue.project)} 653 assert_nil result.detect {|issue| !User.current.member_of?(issue.project)}
577 end 654 end
578 655
579 def test_filter_watched_issues 656 def test_filter_watched_issues
580 User.current = User.find(1) 657 User.current = User.find(1)
581 query = Query.new(:name => '_', :filters => { 'watcher_id' => {:operator => '=', :values => ['me']}}) 658 query = IssueQuery.new(:name => '_', :filters => { 'watcher_id' => {:operator => '=', :values => ['me']}})
582 result = find_issues_with_query(query) 659 result = find_issues_with_query(query)
583 assert_not_nil result 660 assert_not_nil result
584 assert !result.empty? 661 assert !result.empty?
585 assert_equal Issue.visible.watched_by(User.current).sort_by(&:id), result.sort_by(&:id) 662 assert_equal Issue.visible.watched_by(User.current).sort_by(&:id), result.sort_by(&:id)
586 User.current = nil 663 User.current = nil
587 end 664 end
588 665
589 def test_filter_unwatched_issues 666 def test_filter_unwatched_issues
590 User.current = User.find(1) 667 User.current = User.find(1)
591 query = Query.new(:name => '_', :filters => { 'watcher_id' => {:operator => '!', :values => ['me']}}) 668 query = IssueQuery.new(:name => '_', :filters => { 'watcher_id' => {:operator => '!', :values => ['me']}})
592 result = find_issues_with_query(query) 669 result = find_issues_with_query(query)
593 assert_not_nil result 670 assert_not_nil result
594 assert !result.empty? 671 assert !result.empty?
595 assert_equal((Issue.visible - Issue.watched_by(User.current)).sort_by(&:id).size, result.sort_by(&:id).size) 672 assert_equal((Issue.visible - Issue.watched_by(User.current)).sort_by(&:id).size, result.sort_by(&:id).size)
596 User.current = nil 673 User.current = nil
597 end 674 end
598 675
676 def test_filter_on_custom_field_should_ignore_projects_with_field_disabled
677 field = IssueCustomField.generate!(:trackers => Tracker.all, :project_ids => [1, 3, 4], :is_filter => true)
678 Issue.generate!(:project_id => 3, :tracker_id => 2, :custom_field_values => {field.id.to_s => 'Foo'})
679 Issue.generate!(:project_id => 4, :tracker_id => 2, :custom_field_values => {field.id.to_s => 'Foo'})
680
681 query = IssueQuery.new(:name => '_', :project => Project.find(1))
682 query.filters = {"cf_#{field.id}" => {:operator => '=', :values => ['Foo']}}
683 assert_equal 2, find_issues_with_query(query).size
684
685 field.project_ids = [1, 3] # Disable the field for project 4
686 field.save!
687 assert_equal 1, find_issues_with_query(query).size
688 end
689
690 def test_filter_on_custom_field_should_ignore_trackers_with_field_disabled
691 field = IssueCustomField.generate!(:tracker_ids => [1, 2], :is_for_all => true, :is_filter => true)
692 Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {field.id.to_s => 'Foo'})
693 Issue.generate!(:project_id => 1, :tracker_id => 2, :custom_field_values => {field.id.to_s => 'Foo'})
694
695 query = IssueQuery.new(:name => '_', :project => Project.find(1))
696 query.filters = {"cf_#{field.id}" => {:operator => '=', :values => ['Foo']}}
697 assert_equal 2, find_issues_with_query(query).size
698
699 field.tracker_ids = [1] # Disable the field for tracker 2
700 field.save!
701 assert_equal 1, find_issues_with_query(query).size
702 end
703
599 def test_filter_on_project_custom_field 704 def test_filter_on_project_custom_field
600 field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string') 705 field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
601 CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo') 706 CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
602 CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo') 707 CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
603 708
604 query = Query.new(:name => '_') 709 query = IssueQuery.new(:name => '_')
605 filter_name = "project.cf_#{field.id}" 710 filter_name = "project.cf_#{field.id}"
606 assert_include filter_name, query.available_filters.keys 711 assert_include filter_name, query.available_filters.keys
607 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}} 712 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
608 assert_equal [3, 5], find_issues_with_query(query).map(&:project_id).uniq.sort 713 assert_equal [3, 5], find_issues_with_query(query).map(&:project_id).uniq.sort
609 end 714 end
610 715
611 def test_filter_on_author_custom_field 716 def test_filter_on_author_custom_field
612 field = UserCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string') 717 field = UserCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
613 CustomValue.create!(:custom_field => field, :customized => User.find(3), :value => 'Foo') 718 CustomValue.create!(:custom_field => field, :customized => User.find(3), :value => 'Foo')
614 719
615 query = Query.new(:name => '_') 720 query = IssueQuery.new(:name => '_')
616 filter_name = "author.cf_#{field.id}" 721 filter_name = "author.cf_#{field.id}"
617 assert_include filter_name, query.available_filters.keys 722 assert_include filter_name, query.available_filters.keys
618 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}} 723 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
619 assert_equal [3], find_issues_with_query(query).map(&:author_id).uniq.sort 724 assert_equal [3], find_issues_with_query(query).map(&:author_id).uniq.sort
620 end 725 end
621 726
622 def test_filter_on_assigned_to_custom_field 727 def test_filter_on_assigned_to_custom_field
623 field = UserCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string') 728 field = UserCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
624 CustomValue.create!(:custom_field => field, :customized => User.find(3), :value => 'Foo') 729 CustomValue.create!(:custom_field => field, :customized => User.find(3), :value => 'Foo')
625 730
626 query = Query.new(:name => '_') 731 query = IssueQuery.new(:name => '_')
627 filter_name = "assigned_to.cf_#{field.id}" 732 filter_name = "assigned_to.cf_#{field.id}"
628 assert_include filter_name, query.available_filters.keys 733 assert_include filter_name, query.available_filters.keys
629 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}} 734 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
630 assert_equal [3], find_issues_with_query(query).map(&:assigned_to_id).uniq.sort 735 assert_equal [3], find_issues_with_query(query).map(&:assigned_to_id).uniq.sort
631 end 736 end
632 737
633 def test_filter_on_fixed_version_custom_field 738 def test_filter_on_fixed_version_custom_field
634 field = VersionCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string') 739 field = VersionCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
635 CustomValue.create!(:custom_field => field, :customized => Version.find(2), :value => 'Foo') 740 CustomValue.create!(:custom_field => field, :customized => Version.find(2), :value => 'Foo')
636 741
637 query = Query.new(:name => '_') 742 query = IssueQuery.new(:name => '_')
638 filter_name = "fixed_version.cf_#{field.id}" 743 filter_name = "fixed_version.cf_#{field.id}"
639 assert_include filter_name, query.available_filters.keys 744 assert_include filter_name, query.available_filters.keys
640 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}} 745 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
641 assert_equal [2], find_issues_with_query(query).map(&:fixed_version_id).uniq.sort 746 assert_equal [2], find_issues_with_query(query).map(&:fixed_version_id).uniq.sort
642 end 747 end
644 def test_filter_on_relations_with_a_specific_issue 749 def test_filter_on_relations_with_a_specific_issue
645 IssueRelation.delete_all 750 IssueRelation.delete_all
646 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2)) 751 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
647 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1)) 752 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1))
648 753
649 query = Query.new(:name => '_') 754 query = IssueQuery.new(:name => '_')
650 query.filters = {"relates" => {:operator => '=', :values => ['1']}} 755 query.filters = {"relates" => {:operator => '=', :values => ['1']}}
651 assert_equal [2, 3], find_issues_with_query(query).map(&:id).sort 756 assert_equal [2, 3], find_issues_with_query(query).map(&:id).sort
652 757
653 query = Query.new(:name => '_') 758 query = IssueQuery.new(:name => '_')
654 query.filters = {"relates" => {:operator => '=', :values => ['2']}} 759 query.filters = {"relates" => {:operator => '=', :values => ['2']}}
655 assert_equal [1], find_issues_with_query(query).map(&:id).sort 760 assert_equal [1], find_issues_with_query(query).map(&:id).sort
656 end 761 end
657 762
658 def test_filter_on_relations_with_any_issues_in_a_project 763 def test_filter_on_relations_with_any_issues_in_a_project
661 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first) 766 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first)
662 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(2).issues.first) 767 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(2).issues.first)
663 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(3).issues.first) 768 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(3).issues.first)
664 end 769 end
665 770
666 query = Query.new(:name => '_') 771 query = IssueQuery.new(:name => '_')
667 query.filters = {"relates" => {:operator => '=p', :values => ['2']}} 772 query.filters = {"relates" => {:operator => '=p', :values => ['2']}}
668 assert_equal [1, 2], find_issues_with_query(query).map(&:id).sort 773 assert_equal [1, 2], find_issues_with_query(query).map(&:id).sort
669 774
670 query = Query.new(:name => '_') 775 query = IssueQuery.new(:name => '_')
671 query.filters = {"relates" => {:operator => '=p', :values => ['3']}} 776 query.filters = {"relates" => {:operator => '=p', :values => ['3']}}
672 assert_equal [1], find_issues_with_query(query).map(&:id).sort 777 assert_equal [1], find_issues_with_query(query).map(&:id).sort
673 778
674 query = Query.new(:name => '_') 779 query = IssueQuery.new(:name => '_')
675 query.filters = {"relates" => {:operator => '=p', :values => ['4']}} 780 query.filters = {"relates" => {:operator => '=p', :values => ['4']}}
676 assert_equal [], find_issues_with_query(query).map(&:id).sort 781 assert_equal [], find_issues_with_query(query).map(&:id).sort
677 end 782 end
678 783
679 def test_filter_on_relations_with_any_issues_not_in_a_project 784 def test_filter_on_relations_with_any_issues_not_in_a_project
682 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first) 787 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first)
683 #IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(1).issues.first) 788 #IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(1).issues.first)
684 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(3).issues.first) 789 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(3).issues.first)
685 end 790 end
686 791
687 query = Query.new(:name => '_') 792 query = IssueQuery.new(:name => '_')
688 query.filters = {"relates" => {:operator => '=!p', :values => ['1']}} 793 query.filters = {"relates" => {:operator => '=!p', :values => ['1']}}
689 assert_equal [1], find_issues_with_query(query).map(&:id).sort 794 assert_equal [1], find_issues_with_query(query).map(&:id).sort
690 end 795 end
691 796
692 def test_filter_on_relations_with_no_issues_in_a_project 797 def test_filter_on_relations_with_no_issues_in_a_project
695 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first) 800 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first)
696 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(3).issues.first) 801 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(3).issues.first)
697 IssueRelation.create!(:relation_type => "relates", :issue_to => Project.find(2).issues.first, :issue_from => Issue.find(3)) 802 IssueRelation.create!(:relation_type => "relates", :issue_to => Project.find(2).issues.first, :issue_from => Issue.find(3))
698 end 803 end
699 804
700 query = Query.new(:name => '_') 805 query = IssueQuery.new(:name => '_')
701 query.filters = {"relates" => {:operator => '!p', :values => ['2']}} 806 query.filters = {"relates" => {:operator => '!p', :values => ['2']}}
702 ids = find_issues_with_query(query).map(&:id).sort 807 ids = find_issues_with_query(query).map(&:id).sort
703 assert_include 2, ids 808 assert_include 2, ids
704 assert_not_include 1, ids 809 assert_not_include 1, ids
705 assert_not_include 3, ids 810 assert_not_include 3, ids
708 def test_filter_on_relations_with_no_issues 813 def test_filter_on_relations_with_no_issues
709 IssueRelation.delete_all 814 IssueRelation.delete_all
710 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2)) 815 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
711 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1)) 816 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1))
712 817
713 query = Query.new(:name => '_') 818 query = IssueQuery.new(:name => '_')
714 query.filters = {"relates" => {:operator => '!*', :values => ['']}} 819 query.filters = {"relates" => {:operator => '!*', :values => ['']}}
715 ids = find_issues_with_query(query).map(&:id) 820 ids = find_issues_with_query(query).map(&:id)
716 assert_equal [], ids & [1, 2, 3] 821 assert_equal [], ids & [1, 2, 3]
717 assert_include 4, ids 822 assert_include 4, ids
718 end 823 end
720 def test_filter_on_relations_with_any_issues 825 def test_filter_on_relations_with_any_issues
721 IssueRelation.delete_all 826 IssueRelation.delete_all
722 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2)) 827 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
723 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1)) 828 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1))
724 829
725 query = Query.new(:name => '_') 830 query = IssueQuery.new(:name => '_')
726 query.filters = {"relates" => {:operator => '*', :values => ['']}} 831 query.filters = {"relates" => {:operator => '*', :values => ['']}}
727 assert_equal [1, 2, 3], find_issues_with_query(query).map(&:id).sort 832 assert_equal [1, 2, 3], find_issues_with_query(query).map(&:id).sort
728 end 833 end
729 834
835 def test_filter_on_relations_should_not_ignore_other_filter
836 issue = Issue.generate!
837 issue1 = Issue.generate!(:status_id => 1)
838 issue2 = Issue.generate!(:status_id => 2)
839 IssueRelation.create!(:relation_type => "relates", :issue_from => issue, :issue_to => issue1)
840 IssueRelation.create!(:relation_type => "relates", :issue_from => issue, :issue_to => issue2)
841
842 query = IssueQuery.new(:name => '_')
843 query.filters = {
844 "status_id" => {:operator => '=', :values => ['1']},
845 "relates" => {:operator => '=', :values => [issue.id.to_s]}
846 }
847 assert_equal [issue1], find_issues_with_query(query)
848 end
849
730 def test_statement_should_be_nil_with_no_filters 850 def test_statement_should_be_nil_with_no_filters
731 q = Query.new(:name => '_') 851 q = IssueQuery.new(:name => '_')
732 q.filters = {} 852 q.filters = {}
733 853
734 assert q.valid? 854 assert q.valid?
735 assert_nil q.statement 855 assert_nil q.statement
736 end 856 end
737 857
738 def test_default_columns 858 def test_default_columns
739 q = Query.new 859 q = IssueQuery.new
740 assert q.columns.any? 860 assert q.columns.any?
741 assert q.inline_columns.any? 861 assert q.inline_columns.any?
742 assert q.block_columns.empty? 862 assert q.block_columns.empty?
743 end 863 end
744 864
745 def test_set_column_names 865 def test_set_column_names
746 q = Query.new 866 q = IssueQuery.new
747 q.column_names = ['tracker', :subject, '', 'unknonw_column'] 867 q.column_names = ['tracker', :subject, '', 'unknonw_column']
748 assert_equal [:tracker, :subject], q.columns.collect {|c| c.name} 868 assert_equal [:id, :tracker, :subject], q.columns.collect {|c| c.name}
749 c = q.columns.first 869 end
750 assert q.has_column?(c) 870
871 def test_has_column_should_accept_a_column_name
872 q = IssueQuery.new
873 q.column_names = ['tracker', :subject]
874 assert q.has_column?(:tracker)
875 assert !q.has_column?(:category)
876 end
877
878 def test_has_column_should_accept_a_column
879 q = IssueQuery.new
880 q.column_names = ['tracker', :subject]
881
882 tracker_column = q.available_columns.detect {|c| c.name==:tracker}
883 assert_kind_of QueryColumn, tracker_column
884 category_column = q.available_columns.detect {|c| c.name==:category}
885 assert_kind_of QueryColumn, category_column
886
887 assert q.has_column?(tracker_column)
888 assert !q.has_column?(category_column)
751 end 889 end
752 890
753 def test_inline_and_block_columns 891 def test_inline_and_block_columns
754 q = Query.new 892 q = IssueQuery.new
755 q.column_names = ['subject', 'description', 'tracker'] 893 q.column_names = ['subject', 'description', 'tracker']
756 894
757 assert_equal [:subject, :tracker], q.inline_columns.map(&:name) 895 assert_equal [:id, :subject, :tracker], q.inline_columns.map(&:name)
758 assert_equal [:description], q.block_columns.map(&:name) 896 assert_equal [:description], q.block_columns.map(&:name)
759 end 897 end
760 898
761 def test_custom_field_columns_should_be_inline 899 def test_custom_field_columns_should_be_inline
762 q = Query.new 900 q = IssueQuery.new
763 columns = q.available_columns.select {|column| column.is_a? QueryCustomFieldColumn} 901 columns = q.available_columns.select {|column| column.is_a? QueryCustomFieldColumn}
764 assert columns.any? 902 assert columns.any?
765 assert_nil columns.detect {|column| !column.inline?} 903 assert_nil columns.detect {|column| !column.inline?}
766 end 904 end
767 905
768 def test_query_should_preload_spent_hours 906 def test_query_should_preload_spent_hours
769 q = Query.new(:name => '_', :column_names => [:subject, :spent_hours]) 907 q = IssueQuery.new(:name => '_', :column_names => [:subject, :spent_hours])
770 assert q.has_column?(:spent_hours) 908 assert q.has_column?(:spent_hours)
771 issues = q.issues 909 issues = q.issues
772 assert_not_nil issues.first.instance_variable_get("@spent_hours") 910 assert_not_nil issues.first.instance_variable_get("@spent_hours")
773 end 911 end
774 912
775 def test_groupable_columns_should_include_custom_fields 913 def test_groupable_columns_should_include_custom_fields
776 q = Query.new 914 q = IssueQuery.new
777 column = q.groupable_columns.detect {|c| c.name == :cf_1} 915 column = q.groupable_columns.detect {|c| c.name == :cf_1}
778 assert_not_nil column 916 assert_not_nil column
779 assert_kind_of QueryCustomFieldColumn, column 917 assert_kind_of QueryCustomFieldColumn, column
780 end 918 end
781 919
782 def test_groupable_columns_should_not_include_multi_custom_fields 920 def test_groupable_columns_should_not_include_multi_custom_fields
783 field = CustomField.find(1) 921 field = CustomField.find(1)
784 field.update_attribute :multiple, true 922 field.update_attribute :multiple, true
785 923
786 q = Query.new 924 q = IssueQuery.new
787 column = q.groupable_columns.detect {|c| c.name == :cf_1} 925 column = q.groupable_columns.detect {|c| c.name == :cf_1}
788 assert_nil column 926 assert_nil column
789 end 927 end
790 928
791 def test_groupable_columns_should_include_user_custom_fields 929 def test_groupable_columns_should_include_user_custom_fields
792 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1], :field_format => 'user') 930 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1], :field_format => 'user')
793 931
794 q = Query.new 932 q = IssueQuery.new
795 assert q.groupable_columns.detect {|c| c.name == "cf_#{cf.id}".to_sym} 933 assert q.groupable_columns.detect {|c| c.name == "cf_#{cf.id}".to_sym}
796 end 934 end
797 935
798 def test_groupable_columns_should_include_version_custom_fields 936 def test_groupable_columns_should_include_version_custom_fields
799 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1], :field_format => 'version') 937 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1], :field_format => 'version')
800 938
801 q = Query.new 939 q = IssueQuery.new
802 assert q.groupable_columns.detect {|c| c.name == "cf_#{cf.id}".to_sym} 940 assert q.groupable_columns.detect {|c| c.name == "cf_#{cf.id}".to_sym}
803 end 941 end
804 942
805 def test_grouped_with_valid_column 943 def test_grouped_with_valid_column
806 q = Query.new(:group_by => 'status') 944 q = IssueQuery.new(:group_by => 'status')
807 assert q.grouped? 945 assert q.grouped?
808 assert_not_nil q.group_by_column 946 assert_not_nil q.group_by_column
809 assert_equal :status, q.group_by_column.name 947 assert_equal :status, q.group_by_column.name
810 assert_not_nil q.group_by_statement 948 assert_not_nil q.group_by_statement
811 assert_equal 'status', q.group_by_statement 949 assert_equal 'status', q.group_by_statement
812 end 950 end
813 951
814 def test_grouped_with_invalid_column 952 def test_grouped_with_invalid_column
815 q = Query.new(:group_by => 'foo') 953 q = IssueQuery.new(:group_by => 'foo')
816 assert !q.grouped? 954 assert !q.grouped?
817 assert_nil q.group_by_column 955 assert_nil q.group_by_column
818 assert_nil q.group_by_statement 956 assert_nil q.group_by_statement
819 end 957 end
820 958
821 def test_sortable_columns_should_sort_assignees_according_to_user_format_setting 959 def test_sortable_columns_should_sort_assignees_according_to_user_format_setting
822 with_settings :user_format => 'lastname_coma_firstname' do 960 with_settings :user_format => 'lastname_coma_firstname' do
823 q = Query.new 961 q = IssueQuery.new
824 assert q.sortable_columns.has_key?('assigned_to') 962 assert q.sortable_columns.has_key?('assigned_to')
825 assert_equal %w(users.lastname users.firstname users.id), q.sortable_columns['assigned_to'] 963 assert_equal %w(users.lastname users.firstname users.id), q.sortable_columns['assigned_to']
826 end 964 end
827 end 965 end
828 966
829 def test_sortable_columns_should_sort_authors_according_to_user_format_setting 967 def test_sortable_columns_should_sort_authors_according_to_user_format_setting
830 with_settings :user_format => 'lastname_coma_firstname' do 968 with_settings :user_format => 'lastname_coma_firstname' do
831 q = Query.new 969 q = IssueQuery.new
832 assert q.sortable_columns.has_key?('author') 970 assert q.sortable_columns.has_key?('author')
833 assert_equal %w(authors.lastname authors.firstname authors.id), q.sortable_columns['author'] 971 assert_equal %w(authors.lastname authors.firstname authors.id), q.sortable_columns['author']
834 end 972 end
835 end 973 end
836 974
837 def test_sortable_columns_should_include_custom_field 975 def test_sortable_columns_should_include_custom_field
838 q = Query.new 976 q = IssueQuery.new
839 assert q.sortable_columns['cf_1'] 977 assert q.sortable_columns['cf_1']
840 end 978 end
841 979
842 def test_sortable_columns_should_not_include_multi_custom_field 980 def test_sortable_columns_should_not_include_multi_custom_field
843 field = CustomField.find(1) 981 field = CustomField.find(1)
844 field.update_attribute :multiple, true 982 field.update_attribute :multiple, true
845 983
846 q = Query.new 984 q = IssueQuery.new
847 assert !q.sortable_columns['cf_1'] 985 assert !q.sortable_columns['cf_1']
848 end 986 end
849 987
850 def test_default_sort 988 def test_default_sort
851 q = Query.new 989 q = IssueQuery.new
852 assert_equal [], q.sort_criteria 990 assert_equal [], q.sort_criteria
853 end 991 end
854 992
855 def test_set_sort_criteria_with_hash 993 def test_set_sort_criteria_with_hash
856 q = Query.new 994 q = IssueQuery.new
857 q.sort_criteria = {'0' => ['priority', 'desc'], '2' => ['tracker']} 995 q.sort_criteria = {'0' => ['priority', 'desc'], '2' => ['tracker']}
858 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria 996 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
859 end 997 end
860 998
861 def test_set_sort_criteria_with_array 999 def test_set_sort_criteria_with_array
862 q = Query.new 1000 q = IssueQuery.new
863 q.sort_criteria = [['priority', 'desc'], 'tracker'] 1001 q.sort_criteria = [['priority', 'desc'], 'tracker']
864 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria 1002 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
865 end 1003 end
866 1004
867 def test_create_query_with_sort 1005 def test_create_query_with_sort
868 q = Query.new(:name => 'Sorted') 1006 q = IssueQuery.new(:name => 'Sorted')
869 q.sort_criteria = [['priority', 'desc'], 'tracker'] 1007 q.sort_criteria = [['priority', 'desc'], 'tracker']
870 assert q.save 1008 assert q.save
871 q.reload 1009 q.reload
872 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria 1010 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
873 end 1011 end
874 1012
875 def test_sort_by_string_custom_field_asc 1013 def test_sort_by_string_custom_field_asc
876 q = Query.new 1014 q = IssueQuery.new
877 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' } 1015 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
878 assert c 1016 assert c
879 assert c.sortable 1017 assert c.sortable
880 issues = Issue.includes([:assigned_to, :status, :tracker, :project, :priority]).where( 1018 issues = q.issues(:order => "#{c.sortable} ASC")
881 q.statement
882 ).order("#{c.sortable} ASC").all
883 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s} 1019 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
884 assert !values.empty? 1020 assert !values.empty?
885 assert_equal values.sort, values 1021 assert_equal values.sort, values
886 end 1022 end
887 1023
888 def test_sort_by_string_custom_field_desc 1024 def test_sort_by_string_custom_field_desc
889 q = Query.new 1025 q = IssueQuery.new
890 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' } 1026 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
891 assert c 1027 assert c
892 assert c.sortable 1028 assert c.sortable
893 issues = Issue.includes([:assigned_to, :status, :tracker, :project, :priority]).where( 1029 issues = q.issues(:order => "#{c.sortable} DESC")
894 q.statement
895 ).order("#{c.sortable} DESC").all
896 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s} 1030 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
897 assert !values.empty? 1031 assert !values.empty?
898 assert_equal values.sort.reverse, values 1032 assert_equal values.sort.reverse, values
899 end 1033 end
900 1034
901 def test_sort_by_float_custom_field_asc 1035 def test_sort_by_float_custom_field_asc
902 q = Query.new 1036 q = IssueQuery.new
903 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'float' } 1037 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'float' }
904 assert c 1038 assert c
905 assert c.sortable 1039 assert c.sortable
906 issues = Issue.includes([:assigned_to, :status, :tracker, :project, :priority]).where( 1040 issues = q.issues(:order => "#{c.sortable} ASC")
907 q.statement
908 ).order("#{c.sortable} ASC").all
909 values = issues.collect {|i| begin; Kernel.Float(i.custom_value_for(c.custom_field).to_s); rescue; nil; end}.compact 1041 values = issues.collect {|i| begin; Kernel.Float(i.custom_value_for(c.custom_field).to_s); rescue; nil; end}.compact
910 assert !values.empty? 1042 assert !values.empty?
911 assert_equal values.sort, values 1043 assert_equal values.sort, values
912 end 1044 end
913 1045
914 def test_invalid_query_should_raise_query_statement_invalid_error 1046 def test_invalid_query_should_raise_query_statement_invalid_error
915 q = Query.new 1047 q = IssueQuery.new
916 assert_raise Query::StatementInvalid do 1048 assert_raise Query::StatementInvalid do
917 q.issues(:conditions => "foo = 1") 1049 q.issues(:conditions => "foo = 1")
918 end 1050 end
919 end 1051 end
920 1052
921 def test_issue_count 1053 def test_issue_count
922 q = Query.new(:name => '_') 1054 q = IssueQuery.new(:name => '_')
923 issue_count = q.issue_count 1055 issue_count = q.issue_count
924 assert_equal q.issues.size, issue_count 1056 assert_equal q.issues.size, issue_count
925 end 1057 end
926 1058
927 def test_issue_count_with_archived_issues 1059 def test_issue_count_with_archived_issues
933 1065
934 test_issue_count 1066 test_issue_count
935 end 1067 end
936 1068
937 def test_issue_count_by_association_group 1069 def test_issue_count_by_association_group
938 q = Query.new(:name => '_', :group_by => 'assigned_to') 1070 q = IssueQuery.new(:name => '_', :group_by => 'assigned_to')
939 count_by_group = q.issue_count_by_group 1071 count_by_group = q.issue_count_by_group
940 assert_kind_of Hash, count_by_group 1072 assert_kind_of Hash, count_by_group
941 assert_equal %w(NilClass User), count_by_group.keys.collect {|k| k.class.name}.uniq.sort 1073 assert_equal %w(NilClass User), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
942 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq 1074 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
943 assert count_by_group.has_key?(User.find(3)) 1075 assert count_by_group.has_key?(User.find(3))
944 end 1076 end
945 1077
946 def test_issue_count_by_list_custom_field_group 1078 def test_issue_count_by_list_custom_field_group
947 q = Query.new(:name => '_', :group_by => 'cf_1') 1079 q = IssueQuery.new(:name => '_', :group_by => 'cf_1')
948 count_by_group = q.issue_count_by_group 1080 count_by_group = q.issue_count_by_group
949 assert_kind_of Hash, count_by_group 1081 assert_kind_of Hash, count_by_group
950 assert_equal %w(NilClass String), count_by_group.keys.collect {|k| k.class.name}.uniq.sort 1082 assert_equal %w(NilClass String), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
951 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq 1083 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
952 assert count_by_group.has_key?('MySQL') 1084 assert count_by_group.has_key?('MySQL')
953 end 1085 end
954 1086
955 def test_issue_count_by_date_custom_field_group 1087 def test_issue_count_by_date_custom_field_group
956 q = Query.new(:name => '_', :group_by => 'cf_8') 1088 q = IssueQuery.new(:name => '_', :group_by => 'cf_8')
957 count_by_group = q.issue_count_by_group 1089 count_by_group = q.issue_count_by_group
958 assert_kind_of Hash, count_by_group 1090 assert_kind_of Hash, count_by_group
959 assert_equal %w(Date NilClass), count_by_group.keys.collect {|k| k.class.name}.uniq.sort 1091 assert_equal %w(Date NilClass), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
960 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq 1092 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
961 end 1093 end
962 1094
963 def test_issue_count_with_nil_group_only 1095 def test_issue_count_with_nil_group_only
964 Issue.update_all("assigned_to_id = NULL") 1096 Issue.update_all("assigned_to_id = NULL")
965 1097
966 q = Query.new(:name => '_', :group_by => 'assigned_to') 1098 q = IssueQuery.new(:name => '_', :group_by => 'assigned_to')
967 count_by_group = q.issue_count_by_group 1099 count_by_group = q.issue_count_by_group
968 assert_kind_of Hash, count_by_group 1100 assert_kind_of Hash, count_by_group
969 assert_equal 1, count_by_group.keys.size 1101 assert_equal 1, count_by_group.keys.size
970 assert_nil count_by_group.keys.first 1102 assert_nil count_by_group.keys.first
971 end 1103 end
972 1104
973 def test_issue_ids 1105 def test_issue_ids
974 q = Query.new(:name => '_') 1106 q = IssueQuery.new(:name => '_')
975 order = "issues.subject, issues.id" 1107 order = "issues.subject, issues.id"
976 issues = q.issues(:order => order) 1108 issues = q.issues(:order => order)
977 assert_equal issues.map(&:id), q.issue_ids(:order => order) 1109 assert_equal issues.map(&:id), q.issue_ids(:order => order)
978 end 1110 end
979 1111
980 def test_label_for 1112 def test_label_for
981 set_language_if_valid 'en' 1113 set_language_if_valid 'en'
982 q = Query.new 1114 q = IssueQuery.new
983 assert_equal 'Assignee', q.label_for('assigned_to_id') 1115 assert_equal 'Assignee', q.label_for('assigned_to_id')
984 end 1116 end
985 1117
986 def test_label_for_fr 1118 def test_label_for_fr
987 set_language_if_valid 'fr' 1119 set_language_if_valid 'fr'
988 q = Query.new 1120 q = IssueQuery.new
989 s = "Assign\xc3\xa9 \xc3\xa0" 1121 s = "Assign\xc3\xa9 \xc3\xa0"
990 s.force_encoding('UTF-8') if s.respond_to?(:force_encoding) 1122 s.force_encoding('UTF-8') if s.respond_to?(:force_encoding)
991 assert_equal s, q.label_for('assigned_to_id') 1123 assert_equal s, q.label_for('assigned_to_id')
992 end 1124 end
993 1125
995 admin = User.find(1) 1127 admin = User.find(1)
996 manager = User.find(2) 1128 manager = User.find(2)
997 developer = User.find(3) 1129 developer = User.find(3)
998 1130
999 # Public query on project 1 1131 # Public query on project 1
1000 q = Query.find(1) 1132 q = IssueQuery.find(1)
1001 assert q.editable_by?(admin) 1133 assert q.editable_by?(admin)
1002 assert q.editable_by?(manager) 1134 assert q.editable_by?(manager)
1003 assert !q.editable_by?(developer) 1135 assert !q.editable_by?(developer)
1004 1136
1005 # Private query on project 1 1137 # Private query on project 1
1006 q = Query.find(2) 1138 q = IssueQuery.find(2)
1007 assert q.editable_by?(admin) 1139 assert q.editable_by?(admin)
1008 assert !q.editable_by?(manager) 1140 assert !q.editable_by?(manager)
1009 assert q.editable_by?(developer) 1141 assert q.editable_by?(developer)
1010 1142
1011 # Private query for all projects 1143 # Private query for all projects
1012 q = Query.find(3) 1144 q = IssueQuery.find(3)
1013 assert q.editable_by?(admin) 1145 assert q.editable_by?(admin)
1014 assert !q.editable_by?(manager) 1146 assert !q.editable_by?(manager)
1015 assert q.editable_by?(developer) 1147 assert q.editable_by?(developer)
1016 1148
1017 # Public query for all projects 1149 # Public query for all projects
1018 q = Query.find(4) 1150 q = IssueQuery.find(4)
1019 assert q.editable_by?(admin) 1151 assert q.editable_by?(admin)
1020 assert !q.editable_by?(manager) 1152 assert !q.editable_by?(manager)
1021 assert !q.editable_by?(developer) 1153 assert !q.editable_by?(developer)
1022 end 1154 end
1023 1155
1024 def test_visible_scope 1156 def test_visible_scope
1025 query_ids = Query.visible(User.anonymous).map(&:id) 1157 query_ids = IssueQuery.visible(User.anonymous).map(&:id)
1026 1158
1027 assert query_ids.include?(1), 'public query on public project was not visible' 1159 assert query_ids.include?(1), 'public query on public project was not visible'
1028 assert query_ids.include?(4), 'public query for all projects was not visible' 1160 assert query_ids.include?(4), 'public query for all projects was not visible'
1029 assert !query_ids.include?(2), 'private query on public project was visible' 1161 assert !query_ids.include?(2), 'private query on public project was visible'
1030 assert !query_ids.include?(3), 'private query for all projects was visible' 1162 assert !query_ids.include?(3), 'private query for all projects was visible'
1031 assert !query_ids.include?(7), 'public query on private project was visible' 1163 assert !query_ids.include?(7), 'public query on private project was visible'
1032 end 1164 end
1033 1165
1034 context "#available_filters" do 1166 def test_query_with_public_visibility_should_be_visible_to_anyone
1035 setup do 1167 q = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_PUBLIC)
1036 @query = Query.new(:name => "_") 1168
1169 assert q.visible?(User.anonymous)
1170 assert IssueQuery.visible(User.anonymous).find_by_id(q.id)
1171
1172 assert q.visible?(User.find(7))
1173 assert IssueQuery.visible(User.find(7)).find_by_id(q.id)
1174
1175 assert q.visible?(User.find(2))
1176 assert IssueQuery.visible(User.find(2)).find_by_id(q.id)
1177
1178 assert q.visible?(User.find(1))
1179 assert IssueQuery.visible(User.find(1)).find_by_id(q.id)
1180 end
1181
1182 def test_query_with_roles_visibility_should_be_visible_to_user_with_role
1183 q = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_ROLES, :role_ids => [1,2])
1184
1185 assert !q.visible?(User.anonymous)
1186 assert_nil IssueQuery.visible(User.anonymous).find_by_id(q.id)
1187
1188 assert !q.visible?(User.find(7))
1189 assert_nil IssueQuery.visible(User.find(7)).find_by_id(q.id)
1190
1191 assert q.visible?(User.find(2))
1192 assert IssueQuery.visible(User.find(2)).find_by_id(q.id)
1193
1194 assert q.visible?(User.find(1))
1195 assert IssueQuery.visible(User.find(1)).find_by_id(q.id)
1196 end
1197
1198 def test_query_with_private_visibility_should_be_visible_to_owner
1199 q = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_PRIVATE, :user => User.find(7))
1200
1201 assert !q.visible?(User.anonymous)
1202 assert_nil IssueQuery.visible(User.anonymous).find_by_id(q.id)
1203
1204 assert q.visible?(User.find(7))
1205 assert IssueQuery.visible(User.find(7)).find_by_id(q.id)
1206
1207 assert !q.visible?(User.find(2))
1208 assert_nil IssueQuery.visible(User.find(2)).find_by_id(q.id)
1209
1210 assert q.visible?(User.find(1))
1211 assert_nil IssueQuery.visible(User.find(1)).find_by_id(q.id)
1212 end
1213
1214 test "#available_filters should include users of visible projects in cross-project view" do
1215 users = IssueQuery.new.available_filters["assigned_to_id"]
1216 assert_not_nil users
1217 assert users[:values].map{|u|u[1]}.include?("3")
1218 end
1219
1220 test "#available_filters should include users of subprojects" do
1221 user1 = User.generate!
1222 user2 = User.generate!
1223 project = Project.find(1)
1224 Member.create!(:principal => user1, :project => project.children.visible.first, :role_ids => [1])
1225
1226 users = IssueQuery.new(:project => project).available_filters["assigned_to_id"]
1227 assert_not_nil users
1228 assert users[:values].map{|u|u[1]}.include?(user1.id.to_s)
1229 assert !users[:values].map{|u|u[1]}.include?(user2.id.to_s)
1230 end
1231
1232 test "#available_filters should include visible projects in cross-project view" do
1233 projects = IssueQuery.new.available_filters["project_id"]
1234 assert_not_nil projects
1235 assert projects[:values].map{|u|u[1]}.include?("1")
1236 end
1237
1238 test "#available_filters should include 'member_of_group' filter" do
1239 query = IssueQuery.new
1240 assert query.available_filters.keys.include?("member_of_group")
1241 assert_equal :list_optional, query.available_filters["member_of_group"][:type]
1242 assert query.available_filters["member_of_group"][:values].present?
1243 assert_equal Group.all.sort.map {|g| [g.name, g.id.to_s]},
1244 query.available_filters["member_of_group"][:values].sort
1245 end
1246
1247 test "#available_filters should include 'assigned_to_role' filter" do
1248 query = IssueQuery.new
1249 assert query.available_filters.keys.include?("assigned_to_role")
1250 assert_equal :list_optional, query.available_filters["assigned_to_role"][:type]
1251
1252 assert query.available_filters["assigned_to_role"][:values].include?(['Manager','1'])
1253 assert query.available_filters["assigned_to_role"][:values].include?(['Developer','2'])
1254 assert query.available_filters["assigned_to_role"][:values].include?(['Reporter','3'])
1255
1256 assert ! query.available_filters["assigned_to_role"][:values].include?(['Non member','4'])
1257 assert ! query.available_filters["assigned_to_role"][:values].include?(['Anonymous','5'])
1258 end
1259
1260 def test_available_filters_should_include_custom_field_according_to_user_visibility
1261 visible_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => true)
1262 hidden_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => false, :role_ids => [1])
1263
1264 with_current_user User.find(3) do
1265 query = IssueQuery.new
1266 assert_include "cf_#{visible_field.id}", query.available_filters.keys
1267 assert_not_include "cf_#{hidden_field.id}", query.available_filters.keys
1037 end 1268 end
1038 1269 end
1039 should "include users of visible projects in cross-project view" do 1270
1040 users = @query.available_filters["assigned_to_id"] 1271 def test_available_columns_should_include_custom_field_according_to_user_visibility
1041 assert_not_nil users 1272 visible_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => true)
1042 assert users[:values].map{|u|u[1]}.include?("3") 1273 hidden_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => false, :role_ids => [1])
1274
1275 with_current_user User.find(3) do
1276 query = IssueQuery.new
1277 assert_include :"cf_#{visible_field.id}", query.available_columns.map(&:name)
1278 assert_not_include :"cf_#{hidden_field.id}", query.available_columns.map(&:name)
1043 end 1279 end
1044
1045 should "include users of subprojects" do
1046 user1 = User.generate!
1047 user2 = User.generate!
1048 project = Project.find(1)
1049 Member.create!(:principal => user1, :project => project.children.visible.first, :role_ids => [1])
1050 @query.project = project
1051
1052 users = @query.available_filters["assigned_to_id"]
1053 assert_not_nil users
1054 assert users[:values].map{|u|u[1]}.include?(user1.id.to_s)
1055 assert !users[:values].map{|u|u[1]}.include?(user2.id.to_s)
1056 end
1057
1058 should "include visible projects in cross-project view" do
1059 projects = @query.available_filters["project_id"]
1060 assert_not_nil projects
1061 assert projects[:values].map{|u|u[1]}.include?("1")
1062 end
1063
1064 context "'member_of_group' filter" do
1065 should "be present" do
1066 assert @query.available_filters.keys.include?("member_of_group")
1067 end
1068
1069 should "be an optional list" do
1070 assert_equal :list_optional, @query.available_filters["member_of_group"][:type]
1071 end
1072
1073 should "have a list of the groups as values" do
1074 Group.destroy_all # No fixtures
1075 group1 = Group.generate!.reload
1076 group2 = Group.generate!.reload
1077
1078 expected_group_list = [
1079 [group1.name, group1.id.to_s],
1080 [group2.name, group2.id.to_s]
1081 ]
1082 assert_equal expected_group_list.sort, @query.available_filters["member_of_group"][:values].sort
1083 end
1084
1085 end
1086
1087 context "'assigned_to_role' filter" do
1088 should "be present" do
1089 assert @query.available_filters.keys.include?("assigned_to_role")
1090 end
1091
1092 should "be an optional list" do
1093 assert_equal :list_optional, @query.available_filters["assigned_to_role"][:type]
1094 end
1095
1096 should "have a list of the Roles as values" do
1097 assert @query.available_filters["assigned_to_role"][:values].include?(['Manager','1'])
1098 assert @query.available_filters["assigned_to_role"][:values].include?(['Developer','2'])
1099 assert @query.available_filters["assigned_to_role"][:values].include?(['Reporter','3'])
1100 end
1101
1102 should "not include the built in Roles as values" do
1103 assert ! @query.available_filters["assigned_to_role"][:values].include?(['Non member','4'])
1104 assert ! @query.available_filters["assigned_to_role"][:values].include?(['Anonymous','5'])
1105 end
1106
1107 end
1108
1109 end 1280 end
1110 1281
1111 context "#statement" do 1282 context "#statement" do
1112 context "with 'member_of_group' filter" do 1283 context "with 'member_of_group' filter" do
1113 setup do 1284 setup do
1125 @group2.users << @user_in_group2 1296 @group2.users << @user_in_group2
1126 1297
1127 end 1298 end
1128 1299
1129 should "search assigned to for users in the group" do 1300 should "search assigned to for users in the group" do
1130 @query = Query.new(:name => '_') 1301 @query = IssueQuery.new(:name => '_')
1131 @query.add_filter('member_of_group', '=', [@group.id.to_s]) 1302 @query.add_filter('member_of_group', '=', [@group.id.to_s])
1132 1303
1133 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@user_in_group.id}','#{@second_user_in_group.id}')" 1304 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@user_in_group.id}','#{@second_user_in_group.id}','#{@group.id}')"
1134 assert_find_issues_with_query_is_successful @query 1305 assert_find_issues_with_query_is_successful @query
1135 end 1306 end
1136 1307
1137 should "search not assigned to any group member (none)" do 1308 should "search not assigned to any group member (none)" do
1138 @query = Query.new(:name => '_') 1309 @query = IssueQuery.new(:name => '_')
1139 @query.add_filter('member_of_group', '!*', ['']) 1310 @query.add_filter('member_of_group', '!*', [''])
1140 1311
1141 # Users not in a group 1312 # Users not in a group
1142 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IS NULL OR #{Issue.table_name}.assigned_to_id NOT IN ('#{@user_in_group.id}','#{@second_user_in_group.id}','#{@user_in_group2.id}')" 1313 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IS NULL OR #{Issue.table_name}.assigned_to_id NOT IN ('#{@user_in_group.id}','#{@second_user_in_group.id}','#{@user_in_group2.id}','#{@group.id}','#{@group2.id}')"
1143 assert_find_issues_with_query_is_successful @query 1314 assert_find_issues_with_query_is_successful @query
1144 end 1315 end
1145 1316
1146 should "search assigned to any group member (all)" do 1317 should "search assigned to any group member (all)" do
1147 @query = Query.new(:name => '_') 1318 @query = IssueQuery.new(:name => '_')
1148 @query.add_filter('member_of_group', '*', ['']) 1319 @query.add_filter('member_of_group', '*', [''])
1149 1320
1150 # Only users in a group 1321 # Only users in a group
1151 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@user_in_group.id}','#{@second_user_in_group.id}','#{@user_in_group2.id}')" 1322 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@user_in_group.id}','#{@second_user_in_group.id}','#{@user_in_group2.id}','#{@group.id}','#{@group2.id}')"
1152 assert_find_issues_with_query_is_successful @query 1323 assert_find_issues_with_query_is_successful @query
1153 end 1324 end
1154 1325
1155 should "return an empty set with = empty group" do 1326 should "return an empty set with = empty group" do
1156 @empty_group = Group.generate! 1327 @empty_group = Group.generate!
1157 @query = Query.new(:name => '_') 1328 @query = IssueQuery.new(:name => '_')
1158 @query.add_filter('member_of_group', '=', [@empty_group.id.to_s]) 1329 @query.add_filter('member_of_group', '=', [@empty_group.id.to_s])
1159 1330
1160 assert_equal [], find_issues_with_query(@query) 1331 assert_equal [], find_issues_with_query(@query)
1161 end 1332 end
1162 1333
1163 should "return issues with ! empty group" do 1334 should "return issues with ! empty group" do
1164 @empty_group = Group.generate! 1335 @empty_group = Group.generate!
1165 @query = Query.new(:name => '_') 1336 @query = IssueQuery.new(:name => '_')
1166 @query.add_filter('member_of_group', '!', [@empty_group.id.to_s]) 1337 @query.add_filter('member_of_group', '!', [@empty_group.id.to_s])
1167 1338
1168 assert_find_issues_with_query_is_successful @query 1339 assert_find_issues_with_query_is_successful @query
1169 end 1340 end
1170 end 1341 end
1180 @boss = User.generate! 1351 @boss = User.generate!
1181 @guest = User.generate! 1352 @guest = User.generate!
1182 User.add_to_project(@manager, @project, @manager_role) 1353 User.add_to_project(@manager, @project, @manager_role)
1183 User.add_to_project(@developer, @project, @developer_role) 1354 User.add_to_project(@developer, @project, @developer_role)
1184 User.add_to_project(@boss, @project, [@manager_role, @developer_role]) 1355 User.add_to_project(@boss, @project, [@manager_role, @developer_role])
1185 1356
1186 @issue1 = Issue.generate!(:project => @project, :assigned_to_id => @manager.id) 1357 @issue1 = Issue.generate!(:project => @project, :assigned_to_id => @manager.id)
1187 @issue2 = Issue.generate!(:project => @project, :assigned_to_id => @developer.id) 1358 @issue2 = Issue.generate!(:project => @project, :assigned_to_id => @developer.id)
1188 @issue3 = Issue.generate!(:project => @project, :assigned_to_id => @boss.id) 1359 @issue3 = Issue.generate!(:project => @project, :assigned_to_id => @boss.id)
1189 @issue4 = Issue.generate!(:project => @project, :assigned_to_id => @guest.id) 1360 @issue4 = Issue.generate!(:project => @project, :assigned_to_id => @guest.id)
1190 @issue5 = Issue.generate!(:project => @project) 1361 @issue5 = Issue.generate!(:project => @project)
1191 end 1362 end
1192 1363
1193 should "search assigned to for users with the Role" do 1364 should "search assigned to for users with the Role" do
1194 @query = Query.new(:name => '_', :project => @project) 1365 @query = IssueQuery.new(:name => '_', :project => @project)
1195 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s]) 1366 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
1196 1367
1197 assert_query_result [@issue1, @issue3], @query 1368 assert_query_result [@issue1, @issue3], @query
1198 end 1369 end
1199 1370
1200 should "search assigned to for users with the Role on the issue project" do 1371 should "search assigned to for users with the Role on the issue project" do
1201 other_project = Project.generate! 1372 other_project = Project.generate!
1202 User.add_to_project(@developer, other_project, @manager_role) 1373 User.add_to_project(@developer, other_project, @manager_role)
1203 1374
1204 @query = Query.new(:name => '_', :project => @project) 1375 @query = IssueQuery.new(:name => '_', :project => @project)
1205 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s]) 1376 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
1206 1377
1207 assert_query_result [@issue1, @issue3], @query 1378 assert_query_result [@issue1, @issue3], @query
1208 end 1379 end
1209 1380
1210 should "return an empty set with empty role" do 1381 should "return an empty set with empty role" do
1211 @empty_role = Role.generate! 1382 @empty_role = Role.generate!
1212 @query = Query.new(:name => '_', :project => @project) 1383 @query = IssueQuery.new(:name => '_', :project => @project)
1213 @query.add_filter('assigned_to_role', '=', [@empty_role.id.to_s]) 1384 @query.add_filter('assigned_to_role', '=', [@empty_role.id.to_s])
1214 1385
1215 assert_query_result [], @query 1386 assert_query_result [], @query
1216 end 1387 end
1217 1388
1218 should "search assigned to for users without the Role" do 1389 should "search assigned to for users without the Role" do
1219 @query = Query.new(:name => '_', :project => @project) 1390 @query = IssueQuery.new(:name => '_', :project => @project)
1220 @query.add_filter('assigned_to_role', '!', [@manager_role.id.to_s]) 1391 @query.add_filter('assigned_to_role', '!', [@manager_role.id.to_s])
1221 1392
1222 assert_query_result [@issue2, @issue4, @issue5], @query 1393 assert_query_result [@issue2, @issue4, @issue5], @query
1223 end 1394 end
1224 1395
1225 should "search assigned to for users not assigned to any Role (none)" do 1396 should "search assigned to for users not assigned to any Role (none)" do
1226 @query = Query.new(:name => '_', :project => @project) 1397 @query = IssueQuery.new(:name => '_', :project => @project)
1227 @query.add_filter('assigned_to_role', '!*', ['']) 1398 @query.add_filter('assigned_to_role', '!*', [''])
1228 1399
1229 assert_query_result [@issue4, @issue5], @query 1400 assert_query_result [@issue4, @issue5], @query
1230 end 1401 end
1231 1402
1232 should "search assigned to for users assigned to any Role (all)" do 1403 should "search assigned to for users assigned to any Role (all)" do
1233 @query = Query.new(:name => '_', :project => @project) 1404 @query = IssueQuery.new(:name => '_', :project => @project)
1234 @query.add_filter('assigned_to_role', '*', ['']) 1405 @query.add_filter('assigned_to_role', '*', [''])
1235 1406
1236 assert_query_result [@issue1, @issue2, @issue3], @query 1407 assert_query_result [@issue1, @issue2, @issue3], @query
1237 end 1408 end
1238 1409
1239 should "return issues with ! empty role" do 1410 should "return issues with ! empty role" do
1240 @empty_role = Role.generate! 1411 @empty_role = Role.generate!
1241 @query = Query.new(:name => '_', :project => @project) 1412 @query = IssueQuery.new(:name => '_', :project => @project)
1242 @query.add_filter('assigned_to_role', '!', [@empty_role.id.to_s]) 1413 @query.add_filter('assigned_to_role', '!', [@empty_role.id.to_s])
1243 1414
1244 assert_query_result [@issue1, @issue2, @issue3, @issue4, @issue5], @query 1415 assert_query_result [@issue1, @issue2, @issue3, @issue4, @issue5], @query
1245 end 1416 end
1246 end 1417 end
1247 end 1418 end
1248
1249 end 1419 end