##// END OF EJS Templates
Set source encoding (#22405)....
Jean-Philippe Lang -
r14970:72e735761127
parent child
Show More
@@ -1,1709 +1,1711
1 # encoding: utf-8
2 #
1 # Redmine - project management software
3 # Redmine - project management software
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
4 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 #
5 #
4 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
8 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
9 # of the License, or (at your option) any later version.
8 #
10 #
9 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # GNU General Public License for more details.
13 #
15 #
14 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
19
18 require File.expand_path('../../test_helper', __FILE__)
20 require File.expand_path('../../test_helper', __FILE__)
19
21
20 class QueryTest < ActiveSupport::TestCase
22 class QueryTest < ActiveSupport::TestCase
21 include Redmine::I18n
23 include Redmine::I18n
22
24
23 fixtures :projects, :enabled_modules, :users, :members,
25 fixtures :projects, :enabled_modules, :users, :members,
24 :member_roles, :roles, :trackers, :issue_statuses,
26 :member_roles, :roles, :trackers, :issue_statuses,
25 :issue_categories, :enumerations, :issues,
27 :issue_categories, :enumerations, :issues,
26 :watchers, :custom_fields, :custom_values, :versions,
28 :watchers, :custom_fields, :custom_values, :versions,
27 :queries,
29 :queries,
28 :projects_trackers,
30 :projects_trackers,
29 :custom_fields_trackers,
31 :custom_fields_trackers,
30 :workflows
32 :workflows
31
33
32 def setup
34 def setup
33 User.current = nil
35 User.current = nil
34 end
36 end
35
37
36 def test_query_with_roles_visibility_should_validate_roles
38 def test_query_with_roles_visibility_should_validate_roles
37 set_language_if_valid 'en'
39 set_language_if_valid 'en'
38 query = IssueQuery.new(:name => 'Query', :visibility => IssueQuery::VISIBILITY_ROLES)
40 query = IssueQuery.new(:name => 'Query', :visibility => IssueQuery::VISIBILITY_ROLES)
39 assert !query.save
41 assert !query.save
40 assert_include "Roles cannot be blank", query.errors.full_messages
42 assert_include "Roles cannot be blank", query.errors.full_messages
41 query.role_ids = [1, 2]
43 query.role_ids = [1, 2]
42 assert query.save
44 assert query.save
43 end
45 end
44
46
45 def test_changing_roles_visibility_should_clear_roles
47 def test_changing_roles_visibility_should_clear_roles
46 query = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_ROLES, :role_ids => [1, 2])
48 query = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_ROLES, :role_ids => [1, 2])
47 assert_equal 2, query.roles.count
49 assert_equal 2, query.roles.count
48
50
49 query.visibility = IssueQuery::VISIBILITY_PUBLIC
51 query.visibility = IssueQuery::VISIBILITY_PUBLIC
50 query.save!
52 query.save!
51 assert_equal 0, query.roles.count
53 assert_equal 0, query.roles.count
52 end
54 end
53
55
54 def test_available_filters_should_be_ordered
56 def test_available_filters_should_be_ordered
55 set_language_if_valid 'en'
57 set_language_if_valid 'en'
56 query = IssueQuery.new
58 query = IssueQuery.new
57 assert_equal 0, query.available_filters.keys.index('status_id')
59 assert_equal 0, query.available_filters.keys.index('status_id')
58 expected_order = [
60 expected_order = [
59 "Status",
61 "Status",
60 "Project",
62 "Project",
61 "Tracker",
63 "Tracker",
62 "Priority"
64 "Priority"
63 ]
65 ]
64 assert_equal expected_order,
66 assert_equal expected_order,
65 (query.available_filters.values.map{|v| v[:name]} & expected_order)
67 (query.available_filters.values.map{|v| v[:name]} & expected_order)
66 end
68 end
67
69
68 def test_available_filters_with_custom_fields_should_be_ordered
70 def test_available_filters_with_custom_fields_should_be_ordered
69 set_language_if_valid 'en'
71 set_language_if_valid 'en'
70 UserCustomField.create!(
72 UserCustomField.create!(
71 :name => 'order test', :field_format => 'string',
73 :name => 'order test', :field_format => 'string',
72 :is_for_all => true, :is_filter => true
74 :is_for_all => true, :is_filter => true
73 )
75 )
74 query = IssueQuery.new
76 query = IssueQuery.new
75 expected_order = [
77 expected_order = [
76 "Searchable field",
78 "Searchable field",
77 "Database",
79 "Database",
78 "Project's Development status",
80 "Project's Development status",
79 "Author's order test",
81 "Author's order test",
80 "Assignee's order test"
82 "Assignee's order test"
81 ]
83 ]
82 assert_equal expected_order,
84 assert_equal expected_order,
83 (query.available_filters.values.map{|v| v[:name]} & expected_order)
85 (query.available_filters.values.map{|v| v[:name]} & expected_order)
84 end
86 end
85
87
86 def test_custom_fields_for_all_projects_should_be_available_in_global_queries
88 def test_custom_fields_for_all_projects_should_be_available_in_global_queries
87 query = IssueQuery.new(:project => nil, :name => '_')
89 query = IssueQuery.new(:project => nil, :name => '_')
88 assert query.available_filters.has_key?('cf_1')
90 assert query.available_filters.has_key?('cf_1')
89 assert !query.available_filters.has_key?('cf_3')
91 assert !query.available_filters.has_key?('cf_3')
90 end
92 end
91
93
92 def test_system_shared_versions_should_be_available_in_global_queries
94 def test_system_shared_versions_should_be_available_in_global_queries
93 Version.find(2).update_attribute :sharing, 'system'
95 Version.find(2).update_attribute :sharing, 'system'
94 query = IssueQuery.new(:project => nil, :name => '_')
96 query = IssueQuery.new(:project => nil, :name => '_')
95 assert query.available_filters.has_key?('fixed_version_id')
97 assert query.available_filters.has_key?('fixed_version_id')
96 assert query.available_filters['fixed_version_id'][:values].detect {|v| v.last == '2'}
98 assert query.available_filters['fixed_version_id'][:values].detect {|v| v.last == '2'}
97 end
99 end
98
100
99 def test_project_filter_in_global_queries
101 def test_project_filter_in_global_queries
100 query = IssueQuery.new(:project => nil, :name => '_')
102 query = IssueQuery.new(:project => nil, :name => '_')
101 project_filter = query.available_filters["project_id"]
103 project_filter = query.available_filters["project_id"]
102 assert_not_nil project_filter
104 assert_not_nil project_filter
103 project_ids = project_filter[:values].map{|p| p[1]}
105 project_ids = project_filter[:values].map{|p| p[1]}
104 assert project_ids.include?("1") #public project
106 assert project_ids.include?("1") #public project
105 assert !project_ids.include?("2") #private project user cannot see
107 assert !project_ids.include?("2") #private project user cannot see
106 end
108 end
107
109
108 def test_available_filters_should_not_include_fields_disabled_on_all_trackers
110 def test_available_filters_should_not_include_fields_disabled_on_all_trackers
109 Tracker.all.each do |tracker|
111 Tracker.all.each do |tracker|
110 tracker.core_fields = Tracker::CORE_FIELDS - ['start_date']
112 tracker.core_fields = Tracker::CORE_FIELDS - ['start_date']
111 tracker.save!
113 tracker.save!
112 end
114 end
113
115
114 query = IssueQuery.new(:name => '_')
116 query = IssueQuery.new(:name => '_')
115 assert_include 'due_date', query.available_filters
117 assert_include 'due_date', query.available_filters
116 assert_not_include 'start_date', query.available_filters
118 assert_not_include 'start_date', query.available_filters
117 end
119 end
118
120
119 def find_issues_with_query(query)
121 def find_issues_with_query(query)
120 Issue.joins(:status, :tracker, :project, :priority).where(
122 Issue.joins(:status, :tracker, :project, :priority).where(
121 query.statement
123 query.statement
122 ).to_a
124 ).to_a
123 end
125 end
124
126
125 def assert_find_issues_with_query_is_successful(query)
127 def assert_find_issues_with_query_is_successful(query)
126 assert_nothing_raised do
128 assert_nothing_raised do
127 find_issues_with_query(query)
129 find_issues_with_query(query)
128 end
130 end
129 end
131 end
130
132
131 def assert_query_statement_includes(query, condition)
133 def assert_query_statement_includes(query, condition)
132 assert_include condition, query.statement
134 assert_include condition, query.statement
133 end
135 end
134
136
135 def assert_query_result(expected, query)
137 def assert_query_result(expected, query)
136 assert_nothing_raised do
138 assert_nothing_raised do
137 assert_equal expected.map(&:id).sort, query.issues.map(&:id).sort
139 assert_equal expected.map(&:id).sort, query.issues.map(&:id).sort
138 assert_equal expected.size, query.issue_count
140 assert_equal expected.size, query.issue_count
139 end
141 end
140 end
142 end
141
143
142 def test_query_should_allow_shared_versions_for_a_project_query
144 def test_query_should_allow_shared_versions_for_a_project_query
143 subproject_version = Version.find(4)
145 subproject_version = Version.find(4)
144 query = IssueQuery.new(:project => Project.find(1), :name => '_')
146 query = IssueQuery.new(:project => Project.find(1), :name => '_')
145 query.add_filter('fixed_version_id', '=', [subproject_version.id.to_s])
147 query.add_filter('fixed_version_id', '=', [subproject_version.id.to_s])
146
148
147 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IN ('4')")
149 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IN ('4')")
148 end
150 end
149
151
150 def test_query_with_multiple_custom_fields
152 def test_query_with_multiple_custom_fields
151 query = IssueQuery.find(1)
153 query = IssueQuery.find(1)
152 assert query.valid?
154 assert query.valid?
153 assert query.statement.include?("#{CustomValue.table_name}.value IN ('MySQL')")
155 assert query.statement.include?("#{CustomValue.table_name}.value IN ('MySQL')")
154 issues = find_issues_with_query(query)
156 issues = find_issues_with_query(query)
155 assert_equal 1, issues.length
157 assert_equal 1, issues.length
156 assert_equal Issue.find(3), issues.first
158 assert_equal Issue.find(3), issues.first
157 end
159 end
158
160
159 def test_operator_none
161 def test_operator_none
160 query = IssueQuery.new(:project => Project.find(1), :name => '_')
162 query = IssueQuery.new(:project => Project.find(1), :name => '_')
161 query.add_filter('fixed_version_id', '!*', [''])
163 query.add_filter('fixed_version_id', '!*', [''])
162 query.add_filter('cf_1', '!*', [''])
164 query.add_filter('cf_1', '!*', [''])
163 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NULL")
165 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NULL")
164 assert query.statement.include?("#{CustomValue.table_name}.value IS NULL OR #{CustomValue.table_name}.value = ''")
166 assert query.statement.include?("#{CustomValue.table_name}.value IS NULL OR #{CustomValue.table_name}.value = ''")
165 find_issues_with_query(query)
167 find_issues_with_query(query)
166 end
168 end
167
169
168 def test_operator_none_for_integer
170 def test_operator_none_for_integer
169 query = IssueQuery.new(:project => Project.find(1), :name => '_')
171 query = IssueQuery.new(:project => Project.find(1), :name => '_')
170 query.add_filter('estimated_hours', '!*', [''])
172 query.add_filter('estimated_hours', '!*', [''])
171 issues = find_issues_with_query(query)
173 issues = find_issues_with_query(query)
172 assert !issues.empty?
174 assert !issues.empty?
173 assert issues.all? {|i| !i.estimated_hours}
175 assert issues.all? {|i| !i.estimated_hours}
174 end
176 end
175
177
176 def test_operator_none_for_date
178 def test_operator_none_for_date
177 query = IssueQuery.new(:project => Project.find(1), :name => '_')
179 query = IssueQuery.new(:project => Project.find(1), :name => '_')
178 query.add_filter('start_date', '!*', [''])
180 query.add_filter('start_date', '!*', [''])
179 issues = find_issues_with_query(query)
181 issues = find_issues_with_query(query)
180 assert !issues.empty?
182 assert !issues.empty?
181 assert issues.all? {|i| i.start_date.nil?}
183 assert issues.all? {|i| i.start_date.nil?}
182 end
184 end
183
185
184 def test_operator_none_for_string_custom_field
186 def test_operator_none_for_string_custom_field
185 CustomField.find(2).update_attribute :default_value, ""
187 CustomField.find(2).update_attribute :default_value, ""
186 query = IssueQuery.new(:project => Project.find(1), :name => '_')
188 query = IssueQuery.new(:project => Project.find(1), :name => '_')
187 query.add_filter('cf_2', '!*', [''])
189 query.add_filter('cf_2', '!*', [''])
188 assert query.has_filter?('cf_2')
190 assert query.has_filter?('cf_2')
189 issues = find_issues_with_query(query)
191 issues = find_issues_with_query(query)
190 assert !issues.empty?
192 assert !issues.empty?
191 assert issues.all? {|i| i.custom_field_value(2).blank?}
193 assert issues.all? {|i| i.custom_field_value(2).blank?}
192 end
194 end
193
195
194 def test_operator_all
196 def test_operator_all
195 query = IssueQuery.new(:project => Project.find(1), :name => '_')
197 query = IssueQuery.new(:project => Project.find(1), :name => '_')
196 query.add_filter('fixed_version_id', '*', [''])
198 query.add_filter('fixed_version_id', '*', [''])
197 query.add_filter('cf_1', '*', [''])
199 query.add_filter('cf_1', '*', [''])
198 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NOT NULL")
200 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NOT NULL")
199 assert query.statement.include?("#{CustomValue.table_name}.value IS NOT NULL AND #{CustomValue.table_name}.value <> ''")
201 assert query.statement.include?("#{CustomValue.table_name}.value IS NOT NULL AND #{CustomValue.table_name}.value <> ''")
200 find_issues_with_query(query)
202 find_issues_with_query(query)
201 end
203 end
202
204
203 def test_operator_all_for_date
205 def test_operator_all_for_date
204 query = IssueQuery.new(:project => Project.find(1), :name => '_')
206 query = IssueQuery.new(:project => Project.find(1), :name => '_')
205 query.add_filter('start_date', '*', [''])
207 query.add_filter('start_date', '*', [''])
206 issues = find_issues_with_query(query)
208 issues = find_issues_with_query(query)
207 assert !issues.empty?
209 assert !issues.empty?
208 assert issues.all? {|i| i.start_date.present?}
210 assert issues.all? {|i| i.start_date.present?}
209 end
211 end
210
212
211 def test_operator_all_for_string_custom_field
213 def test_operator_all_for_string_custom_field
212 query = IssueQuery.new(:project => Project.find(1), :name => '_')
214 query = IssueQuery.new(:project => Project.find(1), :name => '_')
213 query.add_filter('cf_2', '*', [''])
215 query.add_filter('cf_2', '*', [''])
214 assert query.has_filter?('cf_2')
216 assert query.has_filter?('cf_2')
215 issues = find_issues_with_query(query)
217 issues = find_issues_with_query(query)
216 assert !issues.empty?
218 assert !issues.empty?
217 assert issues.all? {|i| i.custom_field_value(2).present?}
219 assert issues.all? {|i| i.custom_field_value(2).present?}
218 end
220 end
219
221
220 def test_numeric_filter_should_not_accept_non_numeric_values
222 def test_numeric_filter_should_not_accept_non_numeric_values
221 query = IssueQuery.new(:name => '_')
223 query = IssueQuery.new(:name => '_')
222 query.add_filter('estimated_hours', '=', ['a'])
224 query.add_filter('estimated_hours', '=', ['a'])
223
225
224 assert query.has_filter?('estimated_hours')
226 assert query.has_filter?('estimated_hours')
225 assert !query.valid?
227 assert !query.valid?
226 end
228 end
227
229
228 def test_operator_is_on_float
230 def test_operator_is_on_float
229 Issue.where(:id => 2).update_all("estimated_hours = 171.2")
231 Issue.where(:id => 2).update_all("estimated_hours = 171.2")
230 query = IssueQuery.new(:name => '_')
232 query = IssueQuery.new(:name => '_')
231 query.add_filter('estimated_hours', '=', ['171.20'])
233 query.add_filter('estimated_hours', '=', ['171.20'])
232 issues = find_issues_with_query(query)
234 issues = find_issues_with_query(query)
233 assert_equal 1, issues.size
235 assert_equal 1, issues.size
234 assert_equal 2, issues.first.id
236 assert_equal 2, issues.first.id
235 end
237 end
236
238
237 def test_operator_is_on_integer_custom_field
239 def test_operator_is_on_integer_custom_field
238 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true, :trackers => Tracker.all)
240 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true, :trackers => Tracker.all)
239 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
241 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
240 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12')
242 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12')
241 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
243 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
242
244
243 query = IssueQuery.new(:name => '_')
245 query = IssueQuery.new(:name => '_')
244 query.add_filter("cf_#{f.id}", '=', ['12'])
246 query.add_filter("cf_#{f.id}", '=', ['12'])
245 issues = find_issues_with_query(query)
247 issues = find_issues_with_query(query)
246 assert_equal 1, issues.size
248 assert_equal 1, issues.size
247 assert_equal 2, issues.first.id
249 assert_equal 2, issues.first.id
248 end
250 end
249
251
250 def test_operator_is_on_integer_custom_field_should_accept_negative_value
252 def test_operator_is_on_integer_custom_field_should_accept_negative_value
251 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true, :trackers => Tracker.all)
253 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true, :trackers => Tracker.all)
252 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
254 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
253 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12')
255 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12')
254 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
256 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
255
257
256 query = IssueQuery.new(:name => '_')
258 query = IssueQuery.new(:name => '_')
257 query.add_filter("cf_#{f.id}", '=', ['-12'])
259 query.add_filter("cf_#{f.id}", '=', ['-12'])
258 assert query.valid?
260 assert query.valid?
259 issues = find_issues_with_query(query)
261 issues = find_issues_with_query(query)
260 assert_equal 1, issues.size
262 assert_equal 1, issues.size
261 assert_equal 2, issues.first.id
263 assert_equal 2, issues.first.id
262 end
264 end
263
265
264 def test_operator_is_on_float_custom_field
266 def test_operator_is_on_float_custom_field
265 f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
267 f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
266 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3')
268 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3')
267 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12.7')
269 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12.7')
268 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
270 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
269
271
270 query = IssueQuery.new(:name => '_')
272 query = IssueQuery.new(:name => '_')
271 query.add_filter("cf_#{f.id}", '=', ['12.7'])
273 query.add_filter("cf_#{f.id}", '=', ['12.7'])
272 issues = find_issues_with_query(query)
274 issues = find_issues_with_query(query)
273 assert_equal 1, issues.size
275 assert_equal 1, issues.size
274 assert_equal 2, issues.first.id
276 assert_equal 2, issues.first.id
275 end
277 end
276
278
277 def test_operator_is_on_float_custom_field_should_accept_negative_value
279 def test_operator_is_on_float_custom_field_should_accept_negative_value
278 f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
280 f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
279 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3')
281 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3')
280 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12.7')
282 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12.7')
281 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
283 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
282
284
283 query = IssueQuery.new(:name => '_')
285 query = IssueQuery.new(:name => '_')
284 query.add_filter("cf_#{f.id}", '=', ['-12.7'])
286 query.add_filter("cf_#{f.id}", '=', ['-12.7'])
285 assert query.valid?
287 assert query.valid?
286 issues = find_issues_with_query(query)
288 issues = find_issues_with_query(query)
287 assert_equal 1, issues.size
289 assert_equal 1, issues.size
288 assert_equal 2, issues.first.id
290 assert_equal 2, issues.first.id
289 end
291 end
290
292
291 def test_operator_is_on_multi_list_custom_field
293 def test_operator_is_on_multi_list_custom_field
292 f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
294 f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
293 :possible_values => ['value1', 'value2', 'value3'], :multiple => true, :trackers => Tracker.all)
295 :possible_values => ['value1', 'value2', 'value3'], :multiple => true, :trackers => Tracker.all)
294 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1')
296 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1')
295 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2')
297 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2')
296 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1')
298 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1')
297
299
298 query = IssueQuery.new(:name => '_')
300 query = IssueQuery.new(:name => '_')
299 query.add_filter("cf_#{f.id}", '=', ['value1'])
301 query.add_filter("cf_#{f.id}", '=', ['value1'])
300 issues = find_issues_with_query(query)
302 issues = find_issues_with_query(query)
301 assert_equal [1, 3], issues.map(&:id).sort
303 assert_equal [1, 3], issues.map(&:id).sort
302
304
303 query = IssueQuery.new(:name => '_')
305 query = IssueQuery.new(:name => '_')
304 query.add_filter("cf_#{f.id}", '=', ['value2'])
306 query.add_filter("cf_#{f.id}", '=', ['value2'])
305 issues = find_issues_with_query(query)
307 issues = find_issues_with_query(query)
306 assert_equal [1], issues.map(&:id).sort
308 assert_equal [1], issues.map(&:id).sort
307 end
309 end
308
310
309 def test_operator_is_not_on_multi_list_custom_field
311 def test_operator_is_not_on_multi_list_custom_field
310 f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
312 f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
311 :possible_values => ['value1', 'value2', 'value3'], :multiple => true, :trackers => Tracker.all)
313 :possible_values => ['value1', 'value2', 'value3'], :multiple => true, :trackers => Tracker.all)
312 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1')
314 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1')
313 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2')
315 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2')
314 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1')
316 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1')
315
317
316 query = IssueQuery.new(:name => '_')
318 query = IssueQuery.new(:name => '_')
317 query.add_filter("cf_#{f.id}", '!', ['value1'])
319 query.add_filter("cf_#{f.id}", '!', ['value1'])
318 issues = find_issues_with_query(query)
320 issues = find_issues_with_query(query)
319 assert !issues.map(&:id).include?(1)
321 assert !issues.map(&:id).include?(1)
320 assert !issues.map(&:id).include?(3)
322 assert !issues.map(&:id).include?(3)
321
323
322 query = IssueQuery.new(:name => '_')
324 query = IssueQuery.new(:name => '_')
323 query.add_filter("cf_#{f.id}", '!', ['value2'])
325 query.add_filter("cf_#{f.id}", '!', ['value2'])
324 issues = find_issues_with_query(query)
326 issues = find_issues_with_query(query)
325 assert !issues.map(&:id).include?(1)
327 assert !issues.map(&:id).include?(1)
326 assert issues.map(&:id).include?(3)
328 assert issues.map(&:id).include?(3)
327 end
329 end
328
330
329 def test_operator_is_on_is_private_field
331 def test_operator_is_on_is_private_field
330 # is_private filter only available for those who can set issues private
332 # is_private filter only available for those who can set issues private
331 User.current = User.find(2)
333 User.current = User.find(2)
332
334
333 query = IssueQuery.new(:name => '_')
335 query = IssueQuery.new(:name => '_')
334 assert query.available_filters.key?('is_private')
336 assert query.available_filters.key?('is_private')
335
337
336 query.add_filter("is_private", '=', ['1'])
338 query.add_filter("is_private", '=', ['1'])
337 issues = find_issues_with_query(query)
339 issues = find_issues_with_query(query)
338 assert issues.any?
340 assert issues.any?
339 assert_nil issues.detect {|issue| !issue.is_private?}
341 assert_nil issues.detect {|issue| !issue.is_private?}
340 ensure
342 ensure
341 User.current = nil
343 User.current = nil
342 end
344 end
343
345
344 def test_operator_is_not_on_is_private_field
346 def test_operator_is_not_on_is_private_field
345 # is_private filter only available for those who can set issues private
347 # is_private filter only available for those who can set issues private
346 User.current = User.find(2)
348 User.current = User.find(2)
347
349
348 query = IssueQuery.new(:name => '_')
350 query = IssueQuery.new(:name => '_')
349 assert query.available_filters.key?('is_private')
351 assert query.available_filters.key?('is_private')
350
352
351 query.add_filter("is_private", '!', ['1'])
353 query.add_filter("is_private", '!', ['1'])
352 issues = find_issues_with_query(query)
354 issues = find_issues_with_query(query)
353 assert issues.any?
355 assert issues.any?
354 assert_nil issues.detect {|issue| issue.is_private?}
356 assert_nil issues.detect {|issue| issue.is_private?}
355 ensure
357 ensure
356 User.current = nil
358 User.current = nil
357 end
359 end
358
360
359 def test_operator_greater_than
361 def test_operator_greater_than
360 query = IssueQuery.new(:project => Project.find(1), :name => '_')
362 query = IssueQuery.new(:project => Project.find(1), :name => '_')
361 query.add_filter('done_ratio', '>=', ['40'])
363 query.add_filter('done_ratio', '>=', ['40'])
362 assert query.statement.include?("#{Issue.table_name}.done_ratio >= 40.0")
364 assert query.statement.include?("#{Issue.table_name}.done_ratio >= 40.0")
363 find_issues_with_query(query)
365 find_issues_with_query(query)
364 end
366 end
365
367
366 def test_operator_greater_than_a_float
368 def test_operator_greater_than_a_float
367 query = IssueQuery.new(:project => Project.find(1), :name => '_')
369 query = IssueQuery.new(:project => Project.find(1), :name => '_')
368 query.add_filter('estimated_hours', '>=', ['40.5'])
370 query.add_filter('estimated_hours', '>=', ['40.5'])
369 assert query.statement.include?("#{Issue.table_name}.estimated_hours >= 40.5")
371 assert query.statement.include?("#{Issue.table_name}.estimated_hours >= 40.5")
370 find_issues_with_query(query)
372 find_issues_with_query(query)
371 end
373 end
372
374
373 def test_operator_greater_than_on_int_custom_field
375 def test_operator_greater_than_on_int_custom_field
374 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
376 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
375 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
377 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
376 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12')
378 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12')
377 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
379 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
378
380
379 query = IssueQuery.new(:project => Project.find(1), :name => '_')
381 query = IssueQuery.new(:project => Project.find(1), :name => '_')
380 query.add_filter("cf_#{f.id}", '>=', ['8'])
382 query.add_filter("cf_#{f.id}", '>=', ['8'])
381 issues = find_issues_with_query(query)
383 issues = find_issues_with_query(query)
382 assert_equal 1, issues.size
384 assert_equal 1, issues.size
383 assert_equal 2, issues.first.id
385 assert_equal 2, issues.first.id
384 end
386 end
385
387
386 def test_operator_lesser_than
388 def test_operator_lesser_than
387 query = IssueQuery.new(:project => Project.find(1), :name => '_')
389 query = IssueQuery.new(:project => Project.find(1), :name => '_')
388 query.add_filter('done_ratio', '<=', ['30'])
390 query.add_filter('done_ratio', '<=', ['30'])
389 assert query.statement.include?("#{Issue.table_name}.done_ratio <= 30.0")
391 assert query.statement.include?("#{Issue.table_name}.done_ratio <= 30.0")
390 find_issues_with_query(query)
392 find_issues_with_query(query)
391 end
393 end
392
394
393 def test_operator_lesser_than_on_custom_field
395 def test_operator_lesser_than_on_custom_field
394 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
396 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
395 query = IssueQuery.new(:project => Project.find(1), :name => '_')
397 query = IssueQuery.new(:project => Project.find(1), :name => '_')
396 query.add_filter("cf_#{f.id}", '<=', ['30'])
398 query.add_filter("cf_#{f.id}", '<=', ['30'])
397 assert_match /CAST.+ <= 30\.0/, query.statement
399 assert_match /CAST.+ <= 30\.0/, query.statement
398 find_issues_with_query(query)
400 find_issues_with_query(query)
399 end
401 end
400
402
401 def test_operator_lesser_than_on_date_custom_field
403 def test_operator_lesser_than_on_date_custom_field
402 f = IssueCustomField.create!(:name => 'filter', :field_format => 'date', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
404 f = IssueCustomField.create!(:name => 'filter', :field_format => 'date', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
403 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '2013-04-11')
405 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '2013-04-11')
404 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '2013-05-14')
406 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '2013-05-14')
405 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
407 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
406
408
407 query = IssueQuery.new(:project => Project.find(1), :name => '_')
409 query = IssueQuery.new(:project => Project.find(1), :name => '_')
408 query.add_filter("cf_#{f.id}", '<=', ['2013-05-01'])
410 query.add_filter("cf_#{f.id}", '<=', ['2013-05-01'])
409 issue_ids = find_issues_with_query(query).map(&:id)
411 issue_ids = find_issues_with_query(query).map(&:id)
410 assert_include 1, issue_ids
412 assert_include 1, issue_ids
411 assert_not_include 2, issue_ids
413 assert_not_include 2, issue_ids
412 assert_not_include 3, issue_ids
414 assert_not_include 3, issue_ids
413 end
415 end
414
416
415 def test_operator_between
417 def test_operator_between
416 query = IssueQuery.new(:project => Project.find(1), :name => '_')
418 query = IssueQuery.new(:project => Project.find(1), :name => '_')
417 query.add_filter('done_ratio', '><', ['30', '40'])
419 query.add_filter('done_ratio', '><', ['30', '40'])
418 assert_include "#{Issue.table_name}.done_ratio BETWEEN 30.0 AND 40.0", query.statement
420 assert_include "#{Issue.table_name}.done_ratio BETWEEN 30.0 AND 40.0", query.statement
419 find_issues_with_query(query)
421 find_issues_with_query(query)
420 end
422 end
421
423
422 def test_operator_between_on_custom_field
424 def test_operator_between_on_custom_field
423 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
425 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
424 query = IssueQuery.new(:project => Project.find(1), :name => '_')
426 query = IssueQuery.new(:project => Project.find(1), :name => '_')
425 query.add_filter("cf_#{f.id}", '><', ['30', '40'])
427 query.add_filter("cf_#{f.id}", '><', ['30', '40'])
426 assert_match /CAST.+ BETWEEN 30.0 AND 40.0/, query.statement
428 assert_match /CAST.+ BETWEEN 30.0 AND 40.0/, query.statement
427 find_issues_with_query(query)
429 find_issues_with_query(query)
428 end
430 end
429
431
430 def test_date_filter_should_not_accept_non_date_values
432 def test_date_filter_should_not_accept_non_date_values
431 query = IssueQuery.new(:name => '_')
433 query = IssueQuery.new(:name => '_')
432 query.add_filter('created_on', '=', ['a'])
434 query.add_filter('created_on', '=', ['a'])
433
435
434 assert query.has_filter?('created_on')
436 assert query.has_filter?('created_on')
435 assert !query.valid?
437 assert !query.valid?
436 end
438 end
437
439
438 def test_date_filter_should_not_accept_invalid_date_values
440 def test_date_filter_should_not_accept_invalid_date_values
439 query = IssueQuery.new(:name => '_')
441 query = IssueQuery.new(:name => '_')
440 query.add_filter('created_on', '=', ['2011-01-34'])
442 query.add_filter('created_on', '=', ['2011-01-34'])
441
443
442 assert query.has_filter?('created_on')
444 assert query.has_filter?('created_on')
443 assert !query.valid?
445 assert !query.valid?
444 end
446 end
445
447
446 def test_relative_date_filter_should_not_accept_non_integer_values
448 def test_relative_date_filter_should_not_accept_non_integer_values
447 query = IssueQuery.new(:name => '_')
449 query = IssueQuery.new(:name => '_')
448 query.add_filter('created_on', '>t-', ['a'])
450 query.add_filter('created_on', '>t-', ['a'])
449
451
450 assert query.has_filter?('created_on')
452 assert query.has_filter?('created_on')
451 assert !query.valid?
453 assert !query.valid?
452 end
454 end
453
455
454 def test_operator_date_equals
456 def test_operator_date_equals
455 query = IssueQuery.new(:name => '_')
457 query = IssueQuery.new(:name => '_')
456 query.add_filter('due_date', '=', ['2011-07-10'])
458 query.add_filter('due_date', '=', ['2011-07-10'])
457 assert_match /issues\.due_date > '#{quoted_date "2011-07-09"} 23:59:59(\.\d+)?' AND issues\.due_date <= '#{quoted_date "2011-07-10"} 23:59:59(\.\d+)?/,
459 assert_match /issues\.due_date > '#{quoted_date "2011-07-09"} 23:59:59(\.\d+)?' AND issues\.due_date <= '#{quoted_date "2011-07-10"} 23:59:59(\.\d+)?/,
458 query.statement
460 query.statement
459 find_issues_with_query(query)
461 find_issues_with_query(query)
460 end
462 end
461
463
462 def test_operator_date_lesser_than
464 def test_operator_date_lesser_than
463 query = IssueQuery.new(:name => '_')
465 query = IssueQuery.new(:name => '_')
464 query.add_filter('due_date', '<=', ['2011-07-10'])
466 query.add_filter('due_date', '<=', ['2011-07-10'])
465 assert_match /issues\.due_date <= '#{quoted_date "2011-07-10"} 23:59:59(\.\d+)?/, query.statement
467 assert_match /issues\.due_date <= '#{quoted_date "2011-07-10"} 23:59:59(\.\d+)?/, query.statement
466 find_issues_with_query(query)
468 find_issues_with_query(query)
467 end
469 end
468
470
469 def test_operator_date_lesser_than_with_timestamp
471 def test_operator_date_lesser_than_with_timestamp
470 query = IssueQuery.new(:name => '_')
472 query = IssueQuery.new(:name => '_')
471 query.add_filter('updated_on', '<=', ['2011-07-10T19:13:52'])
473 query.add_filter('updated_on', '<=', ['2011-07-10T19:13:52'])
472 assert_match /issues\.updated_on <= '#{quoted_date "2011-07-10"} 19:13:52/, query.statement
474 assert_match /issues\.updated_on <= '#{quoted_date "2011-07-10"} 19:13:52/, query.statement
473 find_issues_with_query(query)
475 find_issues_with_query(query)
474 end
476 end
475
477
476 def test_operator_date_greater_than
478 def test_operator_date_greater_than
477 query = IssueQuery.new(:name => '_')
479 query = IssueQuery.new(:name => '_')
478 query.add_filter('due_date', '>=', ['2011-07-10'])
480 query.add_filter('due_date', '>=', ['2011-07-10'])
479 assert_match /issues\.due_date > '#{quoted_date "2011-07-09"} 23:59:59(\.\d+)?'/, query.statement
481 assert_match /issues\.due_date > '#{quoted_date "2011-07-09"} 23:59:59(\.\d+)?'/, query.statement
480 find_issues_with_query(query)
482 find_issues_with_query(query)
481 end
483 end
482
484
483 def test_operator_date_greater_than_with_timestamp
485 def test_operator_date_greater_than_with_timestamp
484 query = IssueQuery.new(:name => '_')
486 query = IssueQuery.new(:name => '_')
485 query.add_filter('updated_on', '>=', ['2011-07-10T19:13:52'])
487 query.add_filter('updated_on', '>=', ['2011-07-10T19:13:52'])
486 assert_match /issues\.updated_on > '#{quoted_date "2011-07-10"} 19:13:51(\.0+)?'/, query.statement
488 assert_match /issues\.updated_on > '#{quoted_date "2011-07-10"} 19:13:51(\.0+)?'/, query.statement
487 find_issues_with_query(query)
489 find_issues_with_query(query)
488 end
490 end
489
491
490 def test_operator_date_between
492 def test_operator_date_between
491 query = IssueQuery.new(:name => '_')
493 query = IssueQuery.new(:name => '_')
492 query.add_filter('due_date', '><', ['2011-06-23', '2011-07-10'])
494 query.add_filter('due_date', '><', ['2011-06-23', '2011-07-10'])
493 assert_match /issues\.due_date > '#{quoted_date "2011-06-22"} 23:59:59(\.\d+)?' AND issues\.due_date <= '#{quoted_date "2011-07-10"} 23:59:59(\.\d+)?'/,
495 assert_match /issues\.due_date > '#{quoted_date "2011-06-22"} 23:59:59(\.\d+)?' AND issues\.due_date <= '#{quoted_date "2011-07-10"} 23:59:59(\.\d+)?'/,
494 query.statement
496 query.statement
495 find_issues_with_query(query)
497 find_issues_with_query(query)
496 end
498 end
497
499
498 def test_operator_in_more_than
500 def test_operator_in_more_than
499 Issue.find(7).update_attribute(:due_date, (Date.today + 15))
501 Issue.find(7).update_attribute(:due_date, (Date.today + 15))
500 query = IssueQuery.new(:project => Project.find(1), :name => '_')
502 query = IssueQuery.new(:project => Project.find(1), :name => '_')
501 query.add_filter('due_date', '>t+', ['15'])
503 query.add_filter('due_date', '>t+', ['15'])
502 issues = find_issues_with_query(query)
504 issues = find_issues_with_query(query)
503 assert !issues.empty?
505 assert !issues.empty?
504 issues.each {|issue| assert(issue.due_date >= (Date.today + 15))}
506 issues.each {|issue| assert(issue.due_date >= (Date.today + 15))}
505 end
507 end
506
508
507 def test_operator_in_less_than
509 def test_operator_in_less_than
508 query = IssueQuery.new(:project => Project.find(1), :name => '_')
510 query = IssueQuery.new(:project => Project.find(1), :name => '_')
509 query.add_filter('due_date', '<t+', ['15'])
511 query.add_filter('due_date', '<t+', ['15'])
510 issues = find_issues_with_query(query)
512 issues = find_issues_with_query(query)
511 assert !issues.empty?
513 assert !issues.empty?
512 issues.each {|issue| assert(issue.due_date <= (Date.today + 15))}
514 issues.each {|issue| assert(issue.due_date <= (Date.today + 15))}
513 end
515 end
514
516
515 def test_operator_in_the_next_days
517 def test_operator_in_the_next_days
516 query = IssueQuery.new(:project => Project.find(1), :name => '_')
518 query = IssueQuery.new(:project => Project.find(1), :name => '_')
517 query.add_filter('due_date', '><t+', ['15'])
519 query.add_filter('due_date', '><t+', ['15'])
518 issues = find_issues_with_query(query)
520 issues = find_issues_with_query(query)
519 assert !issues.empty?
521 assert !issues.empty?
520 issues.each {|issue| assert(issue.due_date >= Date.today && issue.due_date <= (Date.today + 15))}
522 issues.each {|issue| assert(issue.due_date >= Date.today && issue.due_date <= (Date.today + 15))}
521 end
523 end
522
524
523 def test_operator_less_than_ago
525 def test_operator_less_than_ago
524 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
526 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
525 query = IssueQuery.new(:project => Project.find(1), :name => '_')
527 query = IssueQuery.new(:project => Project.find(1), :name => '_')
526 query.add_filter('due_date', '>t-', ['3'])
528 query.add_filter('due_date', '>t-', ['3'])
527 issues = find_issues_with_query(query)
529 issues = find_issues_with_query(query)
528 assert !issues.empty?
530 assert !issues.empty?
529 issues.each {|issue| assert(issue.due_date >= (Date.today - 3))}
531 issues.each {|issue| assert(issue.due_date >= (Date.today - 3))}
530 end
532 end
531
533
532 def test_operator_in_the_past_days
534 def test_operator_in_the_past_days
533 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
535 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
534 query = IssueQuery.new(:project => Project.find(1), :name => '_')
536 query = IssueQuery.new(:project => Project.find(1), :name => '_')
535 query.add_filter('due_date', '><t-', ['3'])
537 query.add_filter('due_date', '><t-', ['3'])
536 issues = find_issues_with_query(query)
538 issues = find_issues_with_query(query)
537 assert !issues.empty?
539 assert !issues.empty?
538 issues.each {|issue| assert(issue.due_date >= (Date.today - 3) && issue.due_date <= Date.today)}
540 issues.each {|issue| assert(issue.due_date >= (Date.today - 3) && issue.due_date <= Date.today)}
539 end
541 end
540
542
541 def test_operator_more_than_ago
543 def test_operator_more_than_ago
542 Issue.find(7).update_attribute(:due_date, (Date.today - 10))
544 Issue.find(7).update_attribute(:due_date, (Date.today - 10))
543 query = IssueQuery.new(:project => Project.find(1), :name => '_')
545 query = IssueQuery.new(:project => Project.find(1), :name => '_')
544 query.add_filter('due_date', '<t-', ['10'])
546 query.add_filter('due_date', '<t-', ['10'])
545 assert query.statement.include?("#{Issue.table_name}.due_date <=")
547 assert query.statement.include?("#{Issue.table_name}.due_date <=")
546 issues = find_issues_with_query(query)
548 issues = find_issues_with_query(query)
547 assert !issues.empty?
549 assert !issues.empty?
548 issues.each {|issue| assert(issue.due_date <= (Date.today - 10))}
550 issues.each {|issue| assert(issue.due_date <= (Date.today - 10))}
549 end
551 end
550
552
551 def test_operator_in
553 def test_operator_in
552 Issue.find(7).update_attribute(:due_date, (Date.today + 2))
554 Issue.find(7).update_attribute(:due_date, (Date.today + 2))
553 query = IssueQuery.new(:project => Project.find(1), :name => '_')
555 query = IssueQuery.new(:project => Project.find(1), :name => '_')
554 query.add_filter('due_date', 't+', ['2'])
556 query.add_filter('due_date', 't+', ['2'])
555 issues = find_issues_with_query(query)
557 issues = find_issues_with_query(query)
556 assert !issues.empty?
558 assert !issues.empty?
557 issues.each {|issue| assert_equal((Date.today + 2), issue.due_date)}
559 issues.each {|issue| assert_equal((Date.today + 2), issue.due_date)}
558 end
560 end
559
561
560 def test_operator_ago
562 def test_operator_ago
561 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
563 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
562 query = IssueQuery.new(:project => Project.find(1), :name => '_')
564 query = IssueQuery.new(:project => Project.find(1), :name => '_')
563 query.add_filter('due_date', 't-', ['3'])
565 query.add_filter('due_date', 't-', ['3'])
564 issues = find_issues_with_query(query)
566 issues = find_issues_with_query(query)
565 assert !issues.empty?
567 assert !issues.empty?
566 issues.each {|issue| assert_equal((Date.today - 3), issue.due_date)}
568 issues.each {|issue| assert_equal((Date.today - 3), issue.due_date)}
567 end
569 end
568
570
569 def test_operator_today
571 def test_operator_today
570 query = IssueQuery.new(:project => Project.find(1), :name => '_')
572 query = IssueQuery.new(:project => Project.find(1), :name => '_')
571 query.add_filter('due_date', 't', [''])
573 query.add_filter('due_date', 't', [''])
572 issues = find_issues_with_query(query)
574 issues = find_issues_with_query(query)
573 assert !issues.empty?
575 assert !issues.empty?
574 issues.each {|issue| assert_equal Date.today, issue.due_date}
576 issues.each {|issue| assert_equal Date.today, issue.due_date}
575 end
577 end
576
578
577 def test_operator_date_periods
579 def test_operator_date_periods
578 %w(t ld w lw l2w m lm y).each do |operator|
580 %w(t ld w lw l2w m lm y).each do |operator|
579 query = IssueQuery.new(:name => '_')
581 query = IssueQuery.new(:name => '_')
580 query.add_filter('due_date', operator, [''])
582 query.add_filter('due_date', operator, [''])
581 assert query.valid?
583 assert query.valid?
582 assert query.issues
584 assert query.issues
583 end
585 end
584 end
586 end
585
587
586 def test_operator_datetime_periods
588 def test_operator_datetime_periods
587 %w(t ld w lw l2w m lm y).each do |operator|
589 %w(t ld w lw l2w m lm y).each do |operator|
588 query = IssueQuery.new(:name => '_')
590 query = IssueQuery.new(:name => '_')
589 query.add_filter('created_on', operator, [''])
591 query.add_filter('created_on', operator, [''])
590 assert query.valid?
592 assert query.valid?
591 assert query.issues
593 assert query.issues
592 end
594 end
593 end
595 end
594
596
595 def test_operator_contains
597 def test_operator_contains
596 issue = Issue.generate!(:subject => 'AbCdEfG')
598 issue = Issue.generate!(:subject => 'AbCdEfG')
597
599
598 query = IssueQuery.new(:name => '_')
600 query = IssueQuery.new(:name => '_')
599 query.add_filter('subject', '~', ['cdeF'])
601 query.add_filter('subject', '~', ['cdeF'])
600 result = find_issues_with_query(query)
602 result = find_issues_with_query(query)
601 assert_include issue, result
603 assert_include issue, result
602 result.each {|issue| assert issue.subject.downcase.include?('cdef') }
604 result.each {|issue| assert issue.subject.downcase.include?('cdef') }
603 end
605 end
604
606
605 def test_operator_contains_with_utf8_string
607 def test_operator_contains_with_utf8_string
606 issue = Issue.generate!(:subject => 'Subject contains Kiểm')
608 issue = Issue.generate!(:subject => 'Subject contains Kiểm')
607
609
608 query = IssueQuery.new(:name => '_')
610 query = IssueQuery.new(:name => '_')
609 query.add_filter('subject', '~', ['Kiểm'])
611 query.add_filter('subject', '~', ['Kiểm'])
610 result = find_issues_with_query(query)
612 result = find_issues_with_query(query)
611 assert_include issue, result
613 assert_include issue, result
612 assert_equal 1, result.size
614 assert_equal 1, result.size
613 end
615 end
614
616
615 def test_operator_does_not_contain
617 def test_operator_does_not_contain
616 issue = Issue.generate!(:subject => 'AbCdEfG')
618 issue = Issue.generate!(:subject => 'AbCdEfG')
617
619
618 query = IssueQuery.new(:name => '_')
620 query = IssueQuery.new(:name => '_')
619 query.add_filter('subject', '!~', ['cdeF'])
621 query.add_filter('subject', '!~', ['cdeF'])
620 result = find_issues_with_query(query)
622 result = find_issues_with_query(query)
621 assert_not_include issue, result
623 assert_not_include issue, result
622 end
624 end
623
625
624 def test_range_for_this_week_with_week_starting_on_monday
626 def test_range_for_this_week_with_week_starting_on_monday
625 I18n.locale = :fr
627 I18n.locale = :fr
626 assert_equal '1', I18n.t(:general_first_day_of_week)
628 assert_equal '1', I18n.t(:general_first_day_of_week)
627
629
628 Date.stubs(:today).returns(Date.parse('2011-04-29'))
630 Date.stubs(:today).returns(Date.parse('2011-04-29'))
629
631
630 query = IssueQuery.new(:project => Project.find(1), :name => '_')
632 query = IssueQuery.new(:project => Project.find(1), :name => '_')
631 query.add_filter('due_date', 'w', [''])
633 query.add_filter('due_date', 'w', [''])
632 assert_match /issues\.due_date > '#{quoted_date "2011-04-24"} 23:59:59(\.\d+)?' AND issues\.due_date <= '#{quoted_date "2011-05-01"} 23:59:59(\.\d+)?/,
634 assert_match /issues\.due_date > '#{quoted_date "2011-04-24"} 23:59:59(\.\d+)?' AND issues\.due_date <= '#{quoted_date "2011-05-01"} 23:59:59(\.\d+)?/,
633 query.statement
635 query.statement
634 I18n.locale = :en
636 I18n.locale = :en
635 end
637 end
636
638
637 def test_range_for_this_week_with_week_starting_on_sunday
639 def test_range_for_this_week_with_week_starting_on_sunday
638 I18n.locale = :en
640 I18n.locale = :en
639 assert_equal '7', I18n.t(:general_first_day_of_week)
641 assert_equal '7', I18n.t(:general_first_day_of_week)
640
642
641 Date.stubs(:today).returns(Date.parse('2011-04-29'))
643 Date.stubs(:today).returns(Date.parse('2011-04-29'))
642
644
643 query = IssueQuery.new(:project => Project.find(1), :name => '_')
645 query = IssueQuery.new(:project => Project.find(1), :name => '_')
644 query.add_filter('due_date', 'w', [''])
646 query.add_filter('due_date', 'w', [''])
645 assert_match /issues\.due_date > '#{quoted_date "2011-04-23"} 23:59:59(\.\d+)?' AND issues\.due_date <= '#{quoted_date "2011-04-30"} 23:59:59(\.\d+)?/,
647 assert_match /issues\.due_date > '#{quoted_date "2011-04-23"} 23:59:59(\.\d+)?' AND issues\.due_date <= '#{quoted_date "2011-04-30"} 23:59:59(\.\d+)?/,
646 query.statement
648 query.statement
647 end
649 end
648
650
649 def test_filter_assigned_to_me
651 def test_filter_assigned_to_me
650 user = User.find(2)
652 user = User.find(2)
651 group = Group.find(10)
653 group = Group.find(10)
652 User.current = user
654 User.current = user
653 i1 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => user)
655 i1 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => user)
654 i2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => group)
656 i2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => group)
655 i3 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => Group.find(11))
657 i3 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => Group.find(11))
656 group.users << user
658 group.users << user
657
659
658 query = IssueQuery.new(:name => '_', :filters => { 'assigned_to_id' => {:operator => '=', :values => ['me']}})
660 query = IssueQuery.new(:name => '_', :filters => { 'assigned_to_id' => {:operator => '=', :values => ['me']}})
659 result = query.issues
661 result = query.issues
660 assert_equal Issue.visible.where(:assigned_to_id => ([2] + user.reload.group_ids)).sort_by(&:id), result.sort_by(&:id)
662 assert_equal Issue.visible.where(:assigned_to_id => ([2] + user.reload.group_ids)).sort_by(&:id), result.sort_by(&:id)
661
663
662 assert result.include?(i1)
664 assert result.include?(i1)
663 assert result.include?(i2)
665 assert result.include?(i2)
664 assert !result.include?(i3)
666 assert !result.include?(i3)
665 end
667 end
666
668
667 def test_user_custom_field_filtered_on_me
669 def test_user_custom_field_filtered_on_me
668 User.current = User.find(2)
670 User.current = User.find(2)
669 cf = IssueCustomField.create!(:field_format => 'user', :is_for_all => true, :is_filter => true, :name => 'User custom field', :tracker_ids => [1])
671 cf = IssueCustomField.create!(:field_format => 'user', :is_for_all => true, :is_filter => true, :name => 'User custom field', :tracker_ids => [1])
670 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '2'}, :subject => 'Test', :author_id => 1)
672 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '2'}, :subject => 'Test', :author_id => 1)
671 issue2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '3'})
673 issue2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '3'})
672
674
673 query = IssueQuery.new(:name => '_', :project => Project.find(1))
675 query = IssueQuery.new(:name => '_', :project => Project.find(1))
674 filter = query.available_filters["cf_#{cf.id}"]
676 filter = query.available_filters["cf_#{cf.id}"]
675 assert_not_nil filter
677 assert_not_nil filter
676 assert_include 'me', filter[:values].map{|v| v[1]}
678 assert_include 'me', filter[:values].map{|v| v[1]}
677
679
678 query.filters = { "cf_#{cf.id}" => {:operator => '=', :values => ['me']}}
680 query.filters = { "cf_#{cf.id}" => {:operator => '=', :values => ['me']}}
679 result = query.issues
681 result = query.issues
680 assert_equal 1, result.size
682 assert_equal 1, result.size
681 assert_equal issue1, result.first
683 assert_equal issue1, result.first
682 end
684 end
683
685
684 def test_filter_on_me_by_anonymous_user
686 def test_filter_on_me_by_anonymous_user
685 User.current = nil
687 User.current = nil
686 query = IssueQuery.new(:name => '_', :filters => { 'assigned_to_id' => {:operator => '=', :values => ['me']}})
688 query = IssueQuery.new(:name => '_', :filters => { 'assigned_to_id' => {:operator => '=', :values => ['me']}})
687 assert_equal [], query.issues
689 assert_equal [], query.issues
688 end
690 end
689
691
690 def test_filter_my_projects
692 def test_filter_my_projects
691 User.current = User.find(2)
693 User.current = User.find(2)
692 query = IssueQuery.new(:name => '_')
694 query = IssueQuery.new(:name => '_')
693 filter = query.available_filters['project_id']
695 filter = query.available_filters['project_id']
694 assert_not_nil filter
696 assert_not_nil filter
695 assert_include 'mine', filter[:values].map{|v| v[1]}
697 assert_include 'mine', filter[:values].map{|v| v[1]}
696
698
697 query.filters = { 'project_id' => {:operator => '=', :values => ['mine']}}
699 query.filters = { 'project_id' => {:operator => '=', :values => ['mine']}}
698 result = query.issues
700 result = query.issues
699 assert_nil result.detect {|issue| !User.current.member_of?(issue.project)}
701 assert_nil result.detect {|issue| !User.current.member_of?(issue.project)}
700 end
702 end
701
703
702 def test_filter_watched_issues
704 def test_filter_watched_issues
703 User.current = User.find(1)
705 User.current = User.find(1)
704 query = IssueQuery.new(:name => '_', :filters => { 'watcher_id' => {:operator => '=', :values => ['me']}})
706 query = IssueQuery.new(:name => '_', :filters => { 'watcher_id' => {:operator => '=', :values => ['me']}})
705 result = find_issues_with_query(query)
707 result = find_issues_with_query(query)
706 assert_not_nil result
708 assert_not_nil result
707 assert !result.empty?
709 assert !result.empty?
708 assert_equal Issue.visible.watched_by(User.current).sort_by(&:id), result.sort_by(&:id)
710 assert_equal Issue.visible.watched_by(User.current).sort_by(&:id), result.sort_by(&:id)
709 User.current = nil
711 User.current = nil
710 end
712 end
711
713
712 def test_filter_unwatched_issues
714 def test_filter_unwatched_issues
713 User.current = User.find(1)
715 User.current = User.find(1)
714 query = IssueQuery.new(:name => '_', :filters => { 'watcher_id' => {:operator => '!', :values => ['me']}})
716 query = IssueQuery.new(:name => '_', :filters => { 'watcher_id' => {:operator => '!', :values => ['me']}})
715 result = find_issues_with_query(query)
717 result = find_issues_with_query(query)
716 assert_not_nil result
718 assert_not_nil result
717 assert !result.empty?
719 assert !result.empty?
718 assert_equal((Issue.visible - Issue.watched_by(User.current)).sort_by(&:id).size, result.sort_by(&:id).size)
720 assert_equal((Issue.visible - Issue.watched_by(User.current)).sort_by(&:id).size, result.sort_by(&:id).size)
719 User.current = nil
721 User.current = nil
720 end
722 end
721
723
722 def test_filter_on_custom_field_should_ignore_projects_with_field_disabled
724 def test_filter_on_custom_field_should_ignore_projects_with_field_disabled
723 field = IssueCustomField.generate!(:trackers => Tracker.all, :project_ids => [1, 3, 4], :is_for_all => false, :is_filter => true)
725 field = IssueCustomField.generate!(:trackers => Tracker.all, :project_ids => [1, 3, 4], :is_for_all => false, :is_filter => true)
724 Issue.generate!(:project_id => 3, :tracker_id => 2, :custom_field_values => {field.id.to_s => 'Foo'})
726 Issue.generate!(:project_id => 3, :tracker_id => 2, :custom_field_values => {field.id.to_s => 'Foo'})
725 Issue.generate!(:project_id => 4, :tracker_id => 2, :custom_field_values => {field.id.to_s => 'Foo'})
727 Issue.generate!(:project_id => 4, :tracker_id => 2, :custom_field_values => {field.id.to_s => 'Foo'})
726
728
727 query = IssueQuery.new(:name => '_', :project => Project.find(1))
729 query = IssueQuery.new(:name => '_', :project => Project.find(1))
728 query.filters = {"cf_#{field.id}" => {:operator => '=', :values => ['Foo']}}
730 query.filters = {"cf_#{field.id}" => {:operator => '=', :values => ['Foo']}}
729 assert_equal 2, find_issues_with_query(query).size
731 assert_equal 2, find_issues_with_query(query).size
730
732
731 field.project_ids = [1, 3] # Disable the field for project 4
733 field.project_ids = [1, 3] # Disable the field for project 4
732 field.save!
734 field.save!
733 assert_equal 1, find_issues_with_query(query).size
735 assert_equal 1, find_issues_with_query(query).size
734 end
736 end
735
737
736 def test_filter_on_custom_field_should_ignore_trackers_with_field_disabled
738 def test_filter_on_custom_field_should_ignore_trackers_with_field_disabled
737 field = IssueCustomField.generate!(:tracker_ids => [1, 2], :is_for_all => true, :is_filter => true)
739 field = IssueCustomField.generate!(:tracker_ids => [1, 2], :is_for_all => true, :is_filter => true)
738 Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {field.id.to_s => 'Foo'})
740 Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {field.id.to_s => 'Foo'})
739 Issue.generate!(:project_id => 1, :tracker_id => 2, :custom_field_values => {field.id.to_s => 'Foo'})
741 Issue.generate!(:project_id => 1, :tracker_id => 2, :custom_field_values => {field.id.to_s => 'Foo'})
740
742
741 query = IssueQuery.new(:name => '_', :project => Project.find(1))
743 query = IssueQuery.new(:name => '_', :project => Project.find(1))
742 query.filters = {"cf_#{field.id}" => {:operator => '=', :values => ['Foo']}}
744 query.filters = {"cf_#{field.id}" => {:operator => '=', :values => ['Foo']}}
743 assert_equal 2, find_issues_with_query(query).size
745 assert_equal 2, find_issues_with_query(query).size
744
746
745 field.tracker_ids = [1] # Disable the field for tracker 2
747 field.tracker_ids = [1] # Disable the field for tracker 2
746 field.save!
748 field.save!
747 assert_equal 1, find_issues_with_query(query).size
749 assert_equal 1, find_issues_with_query(query).size
748 end
750 end
749
751
750 def test_filter_on_project_custom_field
752 def test_filter_on_project_custom_field
751 field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
753 field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
752 CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
754 CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
753 CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
755 CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
754
756
755 query = IssueQuery.new(:name => '_')
757 query = IssueQuery.new(:name => '_')
756 filter_name = "project.cf_#{field.id}"
758 filter_name = "project.cf_#{field.id}"
757 assert_include filter_name, query.available_filters.keys
759 assert_include filter_name, query.available_filters.keys
758 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
760 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
759 assert_equal [3, 5], find_issues_with_query(query).map(&:project_id).uniq.sort
761 assert_equal [3, 5], find_issues_with_query(query).map(&:project_id).uniq.sort
760 end
762 end
761
763
762 def test_filter_on_author_custom_field
764 def test_filter_on_author_custom_field
763 field = UserCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
765 field = UserCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
764 CustomValue.create!(:custom_field => field, :customized => User.find(3), :value => 'Foo')
766 CustomValue.create!(:custom_field => field, :customized => User.find(3), :value => 'Foo')
765
767
766 query = IssueQuery.new(:name => '_')
768 query = IssueQuery.new(:name => '_')
767 filter_name = "author.cf_#{field.id}"
769 filter_name = "author.cf_#{field.id}"
768 assert_include filter_name, query.available_filters.keys
770 assert_include filter_name, query.available_filters.keys
769 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
771 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
770 assert_equal [3], find_issues_with_query(query).map(&:author_id).uniq.sort
772 assert_equal [3], find_issues_with_query(query).map(&:author_id).uniq.sort
771 end
773 end
772
774
773 def test_filter_on_assigned_to_custom_field
775 def test_filter_on_assigned_to_custom_field
774 field = UserCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
776 field = UserCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
775 CustomValue.create!(:custom_field => field, :customized => User.find(3), :value => 'Foo')
777 CustomValue.create!(:custom_field => field, :customized => User.find(3), :value => 'Foo')
776
778
777 query = IssueQuery.new(:name => '_')
779 query = IssueQuery.new(:name => '_')
778 filter_name = "assigned_to.cf_#{field.id}"
780 filter_name = "assigned_to.cf_#{field.id}"
779 assert_include filter_name, query.available_filters.keys
781 assert_include filter_name, query.available_filters.keys
780 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
782 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
781 assert_equal [3], find_issues_with_query(query).map(&:assigned_to_id).uniq.sort
783 assert_equal [3], find_issues_with_query(query).map(&:assigned_to_id).uniq.sort
782 end
784 end
783
785
784 def test_filter_on_fixed_version_custom_field
786 def test_filter_on_fixed_version_custom_field
785 field = VersionCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
787 field = VersionCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
786 CustomValue.create!(:custom_field => field, :customized => Version.find(2), :value => 'Foo')
788 CustomValue.create!(:custom_field => field, :customized => Version.find(2), :value => 'Foo')
787
789
788 query = IssueQuery.new(:name => '_')
790 query = IssueQuery.new(:name => '_')
789 filter_name = "fixed_version.cf_#{field.id}"
791 filter_name = "fixed_version.cf_#{field.id}"
790 assert_include filter_name, query.available_filters.keys
792 assert_include filter_name, query.available_filters.keys
791 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
793 query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
792 assert_equal [2], find_issues_with_query(query).map(&:fixed_version_id).uniq.sort
794 assert_equal [2], find_issues_with_query(query).map(&:fixed_version_id).uniq.sort
793 end
795 end
794
796
795 def test_filter_on_relations_with_a_specific_issue
797 def test_filter_on_relations_with_a_specific_issue
796 IssueRelation.delete_all
798 IssueRelation.delete_all
797 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
799 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
798 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1))
800 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1))
799
801
800 query = IssueQuery.new(:name => '_')
802 query = IssueQuery.new(:name => '_')
801 query.filters = {"relates" => {:operator => '=', :values => ['1']}}
803 query.filters = {"relates" => {:operator => '=', :values => ['1']}}
802 assert_equal [2, 3], find_issues_with_query(query).map(&:id).sort
804 assert_equal [2, 3], find_issues_with_query(query).map(&:id).sort
803
805
804 query = IssueQuery.new(:name => '_')
806 query = IssueQuery.new(:name => '_')
805 query.filters = {"relates" => {:operator => '=', :values => ['2']}}
807 query.filters = {"relates" => {:operator => '=', :values => ['2']}}
806 assert_equal [1], find_issues_with_query(query).map(&:id).sort
808 assert_equal [1], find_issues_with_query(query).map(&:id).sort
807 end
809 end
808
810
809 def test_filter_on_relations_with_any_issues_in_a_project
811 def test_filter_on_relations_with_any_issues_in_a_project
810 IssueRelation.delete_all
812 IssueRelation.delete_all
811 with_settings :cross_project_issue_relations => '1' do
813 with_settings :cross_project_issue_relations => '1' do
812 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first)
814 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first)
813 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(2).issues.first)
815 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(2).issues.first)
814 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(3).issues.first)
816 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(3).issues.first)
815 end
817 end
816
818
817 query = IssueQuery.new(:name => '_')
819 query = IssueQuery.new(:name => '_')
818 query.filters = {"relates" => {:operator => '=p', :values => ['2']}}
820 query.filters = {"relates" => {:operator => '=p', :values => ['2']}}
819 assert_equal [1, 2], find_issues_with_query(query).map(&:id).sort
821 assert_equal [1, 2], find_issues_with_query(query).map(&:id).sort
820
822
821 query = IssueQuery.new(:name => '_')
823 query = IssueQuery.new(:name => '_')
822 query.filters = {"relates" => {:operator => '=p', :values => ['3']}}
824 query.filters = {"relates" => {:operator => '=p', :values => ['3']}}
823 assert_equal [1], find_issues_with_query(query).map(&:id).sort
825 assert_equal [1], find_issues_with_query(query).map(&:id).sort
824
826
825 query = IssueQuery.new(:name => '_')
827 query = IssueQuery.new(:name => '_')
826 query.filters = {"relates" => {:operator => '=p', :values => ['4']}}
828 query.filters = {"relates" => {:operator => '=p', :values => ['4']}}
827 assert_equal [], find_issues_with_query(query).map(&:id).sort
829 assert_equal [], find_issues_with_query(query).map(&:id).sort
828 end
830 end
829
831
830 def test_filter_on_relations_with_any_issues_not_in_a_project
832 def test_filter_on_relations_with_any_issues_not_in_a_project
831 IssueRelation.delete_all
833 IssueRelation.delete_all
832 with_settings :cross_project_issue_relations => '1' do
834 with_settings :cross_project_issue_relations => '1' do
833 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first)
835 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first)
834 #IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(1).issues.first)
836 #IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(1).issues.first)
835 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(3).issues.first)
837 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(3).issues.first)
836 end
838 end
837
839
838 query = IssueQuery.new(:name => '_')
840 query = IssueQuery.new(:name => '_')
839 query.filters = {"relates" => {:operator => '=!p', :values => ['1']}}
841 query.filters = {"relates" => {:operator => '=!p', :values => ['1']}}
840 assert_equal [1], find_issues_with_query(query).map(&:id).sort
842 assert_equal [1], find_issues_with_query(query).map(&:id).sort
841 end
843 end
842
844
843 def test_filter_on_relations_with_no_issues_in_a_project
845 def test_filter_on_relations_with_no_issues_in_a_project
844 IssueRelation.delete_all
846 IssueRelation.delete_all
845 with_settings :cross_project_issue_relations => '1' do
847 with_settings :cross_project_issue_relations => '1' do
846 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first)
848 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first)
847 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(3).issues.first)
849 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(3).issues.first)
848 IssueRelation.create!(:relation_type => "relates", :issue_to => Project.find(2).issues.first, :issue_from => Issue.find(3))
850 IssueRelation.create!(:relation_type => "relates", :issue_to => Project.find(2).issues.first, :issue_from => Issue.find(3))
849 end
851 end
850
852
851 query = IssueQuery.new(:name => '_')
853 query = IssueQuery.new(:name => '_')
852 query.filters = {"relates" => {:operator => '!p', :values => ['2']}}
854 query.filters = {"relates" => {:operator => '!p', :values => ['2']}}
853 ids = find_issues_with_query(query).map(&:id).sort
855 ids = find_issues_with_query(query).map(&:id).sort
854 assert_include 2, ids
856 assert_include 2, ids
855 assert_not_include 1, ids
857 assert_not_include 1, ids
856 assert_not_include 3, ids
858 assert_not_include 3, ids
857 end
859 end
858
860
859 def test_filter_on_relations_with_any_open_issues
861 def test_filter_on_relations_with_any_open_issues
860 IssueRelation.delete_all
862 IssueRelation.delete_all
861 # Issue 1 is blocked by 8, which is closed
863 # Issue 1 is blocked by 8, which is closed
862 IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(1), :issue_to => Issue.find(8))
864 IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(1), :issue_to => Issue.find(8))
863 # Issue 2 is blocked by 3, which is open
865 # Issue 2 is blocked by 3, which is open
864 IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(2), :issue_to => Issue.find(3))
866 IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(2), :issue_to => Issue.find(3))
865
867
866 query = IssueQuery.new(:name => '_')
868 query = IssueQuery.new(:name => '_')
867 query.filters = {"blocked" => {:operator => "*o", :values => ['']}}
869 query.filters = {"blocked" => {:operator => "*o", :values => ['']}}
868 ids = find_issues_with_query(query).map(&:id)
870 ids = find_issues_with_query(query).map(&:id)
869 assert_equal [], ids & [1]
871 assert_equal [], ids & [1]
870 assert_include 2, ids
872 assert_include 2, ids
871 end
873 end
872
874
873 def test_filter_on_relations_with_no_open_issues
875 def test_filter_on_relations_with_no_open_issues
874 IssueRelation.delete_all
876 IssueRelation.delete_all
875 # Issue 1 is blocked by 8, which is closed
877 # Issue 1 is blocked by 8, which is closed
876 IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(1), :issue_to => Issue.find(8))
878 IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(1), :issue_to => Issue.find(8))
877 # Issue 2 is blocked by 3, which is open
879 # Issue 2 is blocked by 3, which is open
878 IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(2), :issue_to => Issue.find(3))
880 IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(2), :issue_to => Issue.find(3))
879
881
880 query = IssueQuery.new(:name => '_')
882 query = IssueQuery.new(:name => '_')
881 query.filters = {"blocked" => {:operator => "!o", :values => ['']}}
883 query.filters = {"blocked" => {:operator => "!o", :values => ['']}}
882 ids = find_issues_with_query(query).map(&:id)
884 ids = find_issues_with_query(query).map(&:id)
883 assert_equal [], ids & [2]
885 assert_equal [], ids & [2]
884 assert_include 1, ids
886 assert_include 1, ids
885 end
887 end
886
888
887 def test_filter_on_relations_with_no_issues
889 def test_filter_on_relations_with_no_issues
888 IssueRelation.delete_all
890 IssueRelation.delete_all
889 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
891 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
890 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1))
892 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1))
891
893
892 query = IssueQuery.new(:name => '_')
894 query = IssueQuery.new(:name => '_')
893 query.filters = {"relates" => {:operator => '!*', :values => ['']}}
895 query.filters = {"relates" => {:operator => '!*', :values => ['']}}
894 ids = find_issues_with_query(query).map(&:id)
896 ids = find_issues_with_query(query).map(&:id)
895 assert_equal [], ids & [1, 2, 3]
897 assert_equal [], ids & [1, 2, 3]
896 assert_include 4, ids
898 assert_include 4, ids
897 end
899 end
898
900
899 def test_filter_on_relations_with_any_issues
901 def test_filter_on_relations_with_any_issues
900 IssueRelation.delete_all
902 IssueRelation.delete_all
901 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
903 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
902 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1))
904 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1))
903
905
904 query = IssueQuery.new(:name => '_')
906 query = IssueQuery.new(:name => '_')
905 query.filters = {"relates" => {:operator => '*', :values => ['']}}
907 query.filters = {"relates" => {:operator => '*', :values => ['']}}
906 assert_equal [1, 2, 3], find_issues_with_query(query).map(&:id).sort
908 assert_equal [1, 2, 3], find_issues_with_query(query).map(&:id).sort
907 end
909 end
908
910
909 def test_filter_on_relations_should_not_ignore_other_filter
911 def test_filter_on_relations_should_not_ignore_other_filter
910 issue = Issue.generate!
912 issue = Issue.generate!
911 issue1 = Issue.generate!(:status_id => 1)
913 issue1 = Issue.generate!(:status_id => 1)
912 issue2 = Issue.generate!(:status_id => 2)
914 issue2 = Issue.generate!(:status_id => 2)
913 IssueRelation.create!(:relation_type => "relates", :issue_from => issue, :issue_to => issue1)
915 IssueRelation.create!(:relation_type => "relates", :issue_from => issue, :issue_to => issue1)
914 IssueRelation.create!(:relation_type => "relates", :issue_from => issue, :issue_to => issue2)
916 IssueRelation.create!(:relation_type => "relates", :issue_from => issue, :issue_to => issue2)
915
917
916 query = IssueQuery.new(:name => '_')
918 query = IssueQuery.new(:name => '_')
917 query.filters = {
919 query.filters = {
918 "status_id" => {:operator => '=', :values => ['1']},
920 "status_id" => {:operator => '=', :values => ['1']},
919 "relates" => {:operator => '=', :values => [issue.id.to_s]}
921 "relates" => {:operator => '=', :values => [issue.id.to_s]}
920 }
922 }
921 assert_equal [issue1], find_issues_with_query(query)
923 assert_equal [issue1], find_issues_with_query(query)
922 end
924 end
923
925
924 def test_filter_on_parent
926 def test_filter_on_parent
925 Issue.delete_all
927 Issue.delete_all
926 parent = Issue.generate_with_descendants!
928 parent = Issue.generate_with_descendants!
927
929
928
930
929 query = IssueQuery.new(:name => '_')
931 query = IssueQuery.new(:name => '_')
930 query.filters = {"parent_id" => {:operator => '=', :values => [parent.id.to_s]}}
932 query.filters = {"parent_id" => {:operator => '=', :values => [parent.id.to_s]}}
931 assert_equal parent.children.map(&:id).sort, find_issues_with_query(query).map(&:id).sort
933 assert_equal parent.children.map(&:id).sort, find_issues_with_query(query).map(&:id).sort
932
934
933 query.filters = {"parent_id" => {:operator => '~', :values => [parent.id.to_s]}}
935 query.filters = {"parent_id" => {:operator => '~', :values => [parent.id.to_s]}}
934 assert_equal parent.descendants.map(&:id).sort, find_issues_with_query(query).map(&:id).sort
936 assert_equal parent.descendants.map(&:id).sort, find_issues_with_query(query).map(&:id).sort
935
937
936 query.filters = {"parent_id" => {:operator => '*', :values => ['']}}
938 query.filters = {"parent_id" => {:operator => '*', :values => ['']}}
937 assert_equal parent.descendants.map(&:id).sort, find_issues_with_query(query).map(&:id).sort
939 assert_equal parent.descendants.map(&:id).sort, find_issues_with_query(query).map(&:id).sort
938
940
939 query.filters = {"parent_id" => {:operator => '!*', :values => ['']}}
941 query.filters = {"parent_id" => {:operator => '!*', :values => ['']}}
940 assert_equal [parent.id], find_issues_with_query(query).map(&:id).sort
942 assert_equal [parent.id], find_issues_with_query(query).map(&:id).sort
941 end
943 end
942
944
943 def test_filter_on_invalid_parent_should_return_no_results
945 def test_filter_on_invalid_parent_should_return_no_results
944 query = IssueQuery.new(:name => '_')
946 query = IssueQuery.new(:name => '_')
945 query.filters = {"parent_id" => {:operator => '=', :values => '99999999999'}}
947 query.filters = {"parent_id" => {:operator => '=', :values => '99999999999'}}
946 assert_equal [], find_issues_with_query(query).map(&:id).sort
948 assert_equal [], find_issues_with_query(query).map(&:id).sort
947
949
948 query.filters = {"parent_id" => {:operator => '~', :values => '99999999999'}}
950 query.filters = {"parent_id" => {:operator => '~', :values => '99999999999'}}
949 assert_equal [], find_issues_with_query(query)
951 assert_equal [], find_issues_with_query(query)
950 end
952 end
951
953
952 def test_filter_on_child
954 def test_filter_on_child
953 Issue.delete_all
955 Issue.delete_all
954 parent = Issue.generate_with_descendants!
956 parent = Issue.generate_with_descendants!
955 child, leaf = parent.children.sort_by(&:id)
957 child, leaf = parent.children.sort_by(&:id)
956 grandchild = child.children.first
958 grandchild = child.children.first
957
959
958
960
959 query = IssueQuery.new(:name => '_')
961 query = IssueQuery.new(:name => '_')
960 query.filters = {"child_id" => {:operator => '=', :values => [grandchild.id.to_s]}}
962 query.filters = {"child_id" => {:operator => '=', :values => [grandchild.id.to_s]}}
961 assert_equal [child.id], find_issues_with_query(query).map(&:id).sort
963 assert_equal [child.id], find_issues_with_query(query).map(&:id).sort
962
964
963 query.filters = {"child_id" => {:operator => '~', :values => [grandchild.id.to_s]}}
965 query.filters = {"child_id" => {:operator => '~', :values => [grandchild.id.to_s]}}
964 assert_equal [parent, child].map(&:id).sort, find_issues_with_query(query).map(&:id).sort
966 assert_equal [parent, child].map(&:id).sort, find_issues_with_query(query).map(&:id).sort
965
967
966 query.filters = {"child_id" => {:operator => '*', :values => ['']}}
968 query.filters = {"child_id" => {:operator => '*', :values => ['']}}
967 assert_equal [parent, child].map(&:id).sort, find_issues_with_query(query).map(&:id).sort
969 assert_equal [parent, child].map(&:id).sort, find_issues_with_query(query).map(&:id).sort
968
970
969 query.filters = {"child_id" => {:operator => '!*', :values => ['']}}
971 query.filters = {"child_id" => {:operator => '!*', :values => ['']}}
970 assert_equal [grandchild, leaf].map(&:id).sort, find_issues_with_query(query).map(&:id).sort
972 assert_equal [grandchild, leaf].map(&:id).sort, find_issues_with_query(query).map(&:id).sort
971 end
973 end
972
974
973 def test_filter_on_invalid_child_should_return_no_results
975 def test_filter_on_invalid_child_should_return_no_results
974 query = IssueQuery.new(:name => '_')
976 query = IssueQuery.new(:name => '_')
975 query.filters = {"child_id" => {:operator => '=', :values => '99999999999'}}
977 query.filters = {"child_id" => {:operator => '=', :values => '99999999999'}}
976 assert_equal [], find_issues_with_query(query)
978 assert_equal [], find_issues_with_query(query)
977
979
978 query.filters = {"child_id" => {:operator => '~', :values => '99999999999'}}
980 query.filters = {"child_id" => {:operator => '~', :values => '99999999999'}}
979 assert_equal [].map(&:id).sort, find_issues_with_query(query)
981 assert_equal [].map(&:id).sort, find_issues_with_query(query)
980 end
982 end
981
983
982 def test_statement_should_be_nil_with_no_filters
984 def test_statement_should_be_nil_with_no_filters
983 q = IssueQuery.new(:name => '_')
985 q = IssueQuery.new(:name => '_')
984 q.filters = {}
986 q.filters = {}
985
987
986 assert q.valid?
988 assert q.valid?
987 assert_nil q.statement
989 assert_nil q.statement
988 end
990 end
989
991
990 def test_available_filters_as_json_should_include_missing_assigned_to_id_values
992 def test_available_filters_as_json_should_include_missing_assigned_to_id_values
991 user = User.generate!
993 user = User.generate!
992 with_current_user User.find(1) do
994 with_current_user User.find(1) do
993 q = IssueQuery.new
995 q = IssueQuery.new
994 q.filters = {"assigned_to_id" => {:operator => '=', :values => user.id.to_s}}
996 q.filters = {"assigned_to_id" => {:operator => '=', :values => user.id.to_s}}
995
997
996 filters = q.available_filters_as_json
998 filters = q.available_filters_as_json
997 assert_include [user.name, user.id.to_s], filters['assigned_to_id']['values']
999 assert_include [user.name, user.id.to_s], filters['assigned_to_id']['values']
998 end
1000 end
999 end
1001 end
1000
1002
1001 def test_available_filters_as_json_should_include_missing_author_id_values
1003 def test_available_filters_as_json_should_include_missing_author_id_values
1002 user = User.generate!
1004 user = User.generate!
1003 with_current_user User.find(1) do
1005 with_current_user User.find(1) do
1004 q = IssueQuery.new
1006 q = IssueQuery.new
1005 q.filters = {"author_id" => {:operator => '=', :values => user.id.to_s}}
1007 q.filters = {"author_id" => {:operator => '=', :values => user.id.to_s}}
1006
1008
1007 filters = q.available_filters_as_json
1009 filters = q.available_filters_as_json
1008 assert_include [user.name, user.id.to_s], filters['author_id']['values']
1010 assert_include [user.name, user.id.to_s], filters['author_id']['values']
1009 end
1011 end
1010 end
1012 end
1011
1013
1012 def test_default_columns
1014 def test_default_columns
1013 q = IssueQuery.new
1015 q = IssueQuery.new
1014 assert q.columns.any?
1016 assert q.columns.any?
1015 assert q.inline_columns.any?
1017 assert q.inline_columns.any?
1016 assert q.block_columns.empty?
1018 assert q.block_columns.empty?
1017 end
1019 end
1018
1020
1019 def test_set_column_names
1021 def test_set_column_names
1020 q = IssueQuery.new
1022 q = IssueQuery.new
1021 q.column_names = ['tracker', :subject, '', 'unknonw_column']
1023 q.column_names = ['tracker', :subject, '', 'unknonw_column']
1022 assert_equal [:id, :tracker, :subject], q.columns.collect {|c| c.name}
1024 assert_equal [:id, :tracker, :subject], q.columns.collect {|c| c.name}
1023 end
1025 end
1024
1026
1025 def test_has_column_should_accept_a_column_name
1027 def test_has_column_should_accept_a_column_name
1026 q = IssueQuery.new
1028 q = IssueQuery.new
1027 q.column_names = ['tracker', :subject]
1029 q.column_names = ['tracker', :subject]
1028 assert q.has_column?(:tracker)
1030 assert q.has_column?(:tracker)
1029 assert !q.has_column?(:category)
1031 assert !q.has_column?(:category)
1030 end
1032 end
1031
1033
1032 def test_has_column_should_accept_a_column
1034 def test_has_column_should_accept_a_column
1033 q = IssueQuery.new
1035 q = IssueQuery.new
1034 q.column_names = ['tracker', :subject]
1036 q.column_names = ['tracker', :subject]
1035
1037
1036 tracker_column = q.available_columns.detect {|c| c.name==:tracker}
1038 tracker_column = q.available_columns.detect {|c| c.name==:tracker}
1037 assert_kind_of QueryColumn, tracker_column
1039 assert_kind_of QueryColumn, tracker_column
1038 category_column = q.available_columns.detect {|c| c.name==:category}
1040 category_column = q.available_columns.detect {|c| c.name==:category}
1039 assert_kind_of QueryColumn, category_column
1041 assert_kind_of QueryColumn, category_column
1040
1042
1041 assert q.has_column?(tracker_column)
1043 assert q.has_column?(tracker_column)
1042 assert !q.has_column?(category_column)
1044 assert !q.has_column?(category_column)
1043 end
1045 end
1044
1046
1045 def test_inline_and_block_columns
1047 def test_inline_and_block_columns
1046 q = IssueQuery.new
1048 q = IssueQuery.new
1047 q.column_names = ['subject', 'description', 'tracker']
1049 q.column_names = ['subject', 'description', 'tracker']
1048
1050
1049 assert_equal [:id, :subject, :tracker], q.inline_columns.map(&:name)
1051 assert_equal [:id, :subject, :tracker], q.inline_columns.map(&:name)
1050 assert_equal [:description], q.block_columns.map(&:name)
1052 assert_equal [:description], q.block_columns.map(&:name)
1051 end
1053 end
1052
1054
1053 def test_custom_field_columns_should_be_inline
1055 def test_custom_field_columns_should_be_inline
1054 q = IssueQuery.new
1056 q = IssueQuery.new
1055 columns = q.available_columns.select {|column| column.is_a? QueryCustomFieldColumn}
1057 columns = q.available_columns.select {|column| column.is_a? QueryCustomFieldColumn}
1056 assert columns.any?
1058 assert columns.any?
1057 assert_nil columns.detect {|column| !column.inline?}
1059 assert_nil columns.detect {|column| !column.inline?}
1058 end
1060 end
1059
1061
1060 def test_query_should_preload_spent_hours
1062 def test_query_should_preload_spent_hours
1061 q = IssueQuery.new(:name => '_', :column_names => [:subject, :spent_hours])
1063 q = IssueQuery.new(:name => '_', :column_names => [:subject, :spent_hours])
1062 assert q.has_column?(:spent_hours)
1064 assert q.has_column?(:spent_hours)
1063 issues = q.issues
1065 issues = q.issues
1064 assert_not_nil issues.first.instance_variable_get("@spent_hours")
1066 assert_not_nil issues.first.instance_variable_get("@spent_hours")
1065 end
1067 end
1066
1068
1067 def test_groupable_columns_should_include_custom_fields
1069 def test_groupable_columns_should_include_custom_fields
1068 q = IssueQuery.new
1070 q = IssueQuery.new
1069 column = q.groupable_columns.detect {|c| c.name == :cf_1}
1071 column = q.groupable_columns.detect {|c| c.name == :cf_1}
1070 assert_not_nil column
1072 assert_not_nil column
1071 assert_kind_of QueryCustomFieldColumn, column
1073 assert_kind_of QueryCustomFieldColumn, column
1072 end
1074 end
1073
1075
1074 def test_groupable_columns_should_not_include_multi_custom_fields
1076 def test_groupable_columns_should_not_include_multi_custom_fields
1075 field = CustomField.find(1)
1077 field = CustomField.find(1)
1076 field.update_attribute :multiple, true
1078 field.update_attribute :multiple, true
1077
1079
1078 q = IssueQuery.new
1080 q = IssueQuery.new
1079 column = q.groupable_columns.detect {|c| c.name == :cf_1}
1081 column = q.groupable_columns.detect {|c| c.name == :cf_1}
1080 assert_nil column
1082 assert_nil column
1081 end
1083 end
1082
1084
1083 def test_groupable_columns_should_include_user_custom_fields
1085 def test_groupable_columns_should_include_user_custom_fields
1084 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1], :field_format => 'user')
1086 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1], :field_format => 'user')
1085
1087
1086 q = IssueQuery.new
1088 q = IssueQuery.new
1087 assert q.groupable_columns.detect {|c| c.name == "cf_#{cf.id}".to_sym}
1089 assert q.groupable_columns.detect {|c| c.name == "cf_#{cf.id}".to_sym}
1088 end
1090 end
1089
1091
1090 def test_groupable_columns_should_include_version_custom_fields
1092 def test_groupable_columns_should_include_version_custom_fields
1091 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1], :field_format => 'version')
1093 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1], :field_format => 'version')
1092
1094
1093 q = IssueQuery.new
1095 q = IssueQuery.new
1094 assert q.groupable_columns.detect {|c| c.name == "cf_#{cf.id}".to_sym}
1096 assert q.groupable_columns.detect {|c| c.name == "cf_#{cf.id}".to_sym}
1095 end
1097 end
1096
1098
1097 def test_grouped_with_valid_column
1099 def test_grouped_with_valid_column
1098 q = IssueQuery.new(:group_by => 'status')
1100 q = IssueQuery.new(:group_by => 'status')
1099 assert q.grouped?
1101 assert q.grouped?
1100 assert_not_nil q.group_by_column
1102 assert_not_nil q.group_by_column
1101 assert_equal :status, q.group_by_column.name
1103 assert_equal :status, q.group_by_column.name
1102 assert_not_nil q.group_by_statement
1104 assert_not_nil q.group_by_statement
1103 assert_equal 'status', q.group_by_statement
1105 assert_equal 'status', q.group_by_statement
1104 end
1106 end
1105
1107
1106 def test_grouped_with_invalid_column
1108 def test_grouped_with_invalid_column
1107 q = IssueQuery.new(:group_by => 'foo')
1109 q = IssueQuery.new(:group_by => 'foo')
1108 assert !q.grouped?
1110 assert !q.grouped?
1109 assert_nil q.group_by_column
1111 assert_nil q.group_by_column
1110 assert_nil q.group_by_statement
1112 assert_nil q.group_by_statement
1111 end
1113 end
1112
1114
1113 def test_sortable_columns_should_sort_assignees_according_to_user_format_setting
1115 def test_sortable_columns_should_sort_assignees_according_to_user_format_setting
1114 with_settings :user_format => 'lastname_comma_firstname' do
1116 with_settings :user_format => 'lastname_comma_firstname' do
1115 q = IssueQuery.new
1117 q = IssueQuery.new
1116 assert q.sortable_columns.has_key?('assigned_to')
1118 assert q.sortable_columns.has_key?('assigned_to')
1117 assert_equal %w(users.lastname users.firstname users.id), q.sortable_columns['assigned_to']
1119 assert_equal %w(users.lastname users.firstname users.id), q.sortable_columns['assigned_to']
1118 end
1120 end
1119 end
1121 end
1120
1122
1121 def test_sortable_columns_should_sort_authors_according_to_user_format_setting
1123 def test_sortable_columns_should_sort_authors_according_to_user_format_setting
1122 with_settings :user_format => 'lastname_comma_firstname' do
1124 with_settings :user_format => 'lastname_comma_firstname' do
1123 q = IssueQuery.new
1125 q = IssueQuery.new
1124 assert q.sortable_columns.has_key?('author')
1126 assert q.sortable_columns.has_key?('author')
1125 assert_equal %w(authors.lastname authors.firstname authors.id), q.sortable_columns['author']
1127 assert_equal %w(authors.lastname authors.firstname authors.id), q.sortable_columns['author']
1126 end
1128 end
1127 end
1129 end
1128
1130
1129 def test_sortable_columns_should_include_custom_field
1131 def test_sortable_columns_should_include_custom_field
1130 q = IssueQuery.new
1132 q = IssueQuery.new
1131 assert q.sortable_columns['cf_1']
1133 assert q.sortable_columns['cf_1']
1132 end
1134 end
1133
1135
1134 def test_sortable_columns_should_not_include_multi_custom_field
1136 def test_sortable_columns_should_not_include_multi_custom_field
1135 field = CustomField.find(1)
1137 field = CustomField.find(1)
1136 field.update_attribute :multiple, true
1138 field.update_attribute :multiple, true
1137
1139
1138 q = IssueQuery.new
1140 q = IssueQuery.new
1139 assert !q.sortable_columns['cf_1']
1141 assert !q.sortable_columns['cf_1']
1140 end
1142 end
1141
1143
1142 def test_default_sort
1144 def test_default_sort
1143 q = IssueQuery.new
1145 q = IssueQuery.new
1144 assert_equal [], q.sort_criteria
1146 assert_equal [], q.sort_criteria
1145 end
1147 end
1146
1148
1147 def test_set_sort_criteria_with_hash
1149 def test_set_sort_criteria_with_hash
1148 q = IssueQuery.new
1150 q = IssueQuery.new
1149 q.sort_criteria = {'0' => ['priority', 'desc'], '2' => ['tracker']}
1151 q.sort_criteria = {'0' => ['priority', 'desc'], '2' => ['tracker']}
1150 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
1152 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
1151 end
1153 end
1152
1154
1153 def test_set_sort_criteria_with_array
1155 def test_set_sort_criteria_with_array
1154 q = IssueQuery.new
1156 q = IssueQuery.new
1155 q.sort_criteria = [['priority', 'desc'], 'tracker']
1157 q.sort_criteria = [['priority', 'desc'], 'tracker']
1156 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
1158 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
1157 end
1159 end
1158
1160
1159 def test_create_query_with_sort
1161 def test_create_query_with_sort
1160 q = IssueQuery.new(:name => 'Sorted')
1162 q = IssueQuery.new(:name => 'Sorted')
1161 q.sort_criteria = [['priority', 'desc'], 'tracker']
1163 q.sort_criteria = [['priority', 'desc'], 'tracker']
1162 assert q.save
1164 assert q.save
1163 q.reload
1165 q.reload
1164 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
1166 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
1165 end
1167 end
1166
1168
1167 def test_sort_by_string_custom_field_asc
1169 def test_sort_by_string_custom_field_asc
1168 q = IssueQuery.new
1170 q = IssueQuery.new
1169 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
1171 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
1170 assert c
1172 assert c
1171 assert c.sortable
1173 assert c.sortable
1172 issues = q.issues(:order => "#{c.sortable} ASC")
1174 issues = q.issues(:order => "#{c.sortable} ASC")
1173 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
1175 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
1174 assert !values.empty?
1176 assert !values.empty?
1175 assert_equal values.sort, values
1177 assert_equal values.sort, values
1176 end
1178 end
1177
1179
1178 def test_sort_by_string_custom_field_desc
1180 def test_sort_by_string_custom_field_desc
1179 q = IssueQuery.new
1181 q = IssueQuery.new
1180 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
1182 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
1181 assert c
1183 assert c
1182 assert c.sortable
1184 assert c.sortable
1183 issues = q.issues(:order => "#{c.sortable} DESC")
1185 issues = q.issues(:order => "#{c.sortable} DESC")
1184 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
1186 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
1185 assert !values.empty?
1187 assert !values.empty?
1186 assert_equal values.sort.reverse, values
1188 assert_equal values.sort.reverse, values
1187 end
1189 end
1188
1190
1189 def test_sort_by_float_custom_field_asc
1191 def test_sort_by_float_custom_field_asc
1190 q = IssueQuery.new
1192 q = IssueQuery.new
1191 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'float' }
1193 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'float' }
1192 assert c
1194 assert c
1193 assert c.sortable
1195 assert c.sortable
1194 issues = q.issues(:order => "#{c.sortable} ASC")
1196 issues = q.issues(:order => "#{c.sortable} ASC")
1195 values = issues.collect {|i| begin; Kernel.Float(i.custom_value_for(c.custom_field).to_s); rescue; nil; end}.compact
1197 values = issues.collect {|i| begin; Kernel.Float(i.custom_value_for(c.custom_field).to_s); rescue; nil; end}.compact
1196 assert !values.empty?
1198 assert !values.empty?
1197 assert_equal values.sort, values
1199 assert_equal values.sort, values
1198 end
1200 end
1199
1201
1200 def test_set_totalable_names
1202 def test_set_totalable_names
1201 q = IssueQuery.new
1203 q = IssueQuery.new
1202 q.totalable_names = ['estimated_hours', :spent_hours, '']
1204 q.totalable_names = ['estimated_hours', :spent_hours, '']
1203 assert_equal [:estimated_hours, :spent_hours], q.totalable_columns.map(&:name)
1205 assert_equal [:estimated_hours, :spent_hours], q.totalable_columns.map(&:name)
1204 end
1206 end
1205
1207
1206 def test_totalable_columns_should_default_to_settings
1208 def test_totalable_columns_should_default_to_settings
1207 with_settings :issue_list_default_totals => ['estimated_hours'] do
1209 with_settings :issue_list_default_totals => ['estimated_hours'] do
1208 q = IssueQuery.new
1210 q = IssueQuery.new
1209 assert_equal [:estimated_hours], q.totalable_columns.map(&:name)
1211 assert_equal [:estimated_hours], q.totalable_columns.map(&:name)
1210 end
1212 end
1211 end
1213 end
1212
1214
1213 def test_available_totalable_columns_should_include_estimated_hours
1215 def test_available_totalable_columns_should_include_estimated_hours
1214 q = IssueQuery.new
1216 q = IssueQuery.new
1215 assert_include :estimated_hours, q.available_totalable_columns.map(&:name)
1217 assert_include :estimated_hours, q.available_totalable_columns.map(&:name)
1216 end
1218 end
1217
1219
1218 def test_available_totalable_columns_should_include_spent_hours
1220 def test_available_totalable_columns_should_include_spent_hours
1219 User.current = User.find(1)
1221 User.current = User.find(1)
1220
1222
1221 q = IssueQuery.new
1223 q = IssueQuery.new
1222 assert_include :spent_hours, q.available_totalable_columns.map(&:name)
1224 assert_include :spent_hours, q.available_totalable_columns.map(&:name)
1223 end
1225 end
1224
1226
1225 def test_available_totalable_columns_should_include_int_custom_field
1227 def test_available_totalable_columns_should_include_int_custom_field
1226 field = IssueCustomField.generate!(:field_format => 'int', :is_for_all => true)
1228 field = IssueCustomField.generate!(:field_format => 'int', :is_for_all => true)
1227 q = IssueQuery.new
1229 q = IssueQuery.new
1228 assert_include "cf_#{field.id}".to_sym, q.available_totalable_columns.map(&:name)
1230 assert_include "cf_#{field.id}".to_sym, q.available_totalable_columns.map(&:name)
1229 end
1231 end
1230
1232
1231 def test_available_totalable_columns_should_include_float_custom_field
1233 def test_available_totalable_columns_should_include_float_custom_field
1232 field = IssueCustomField.generate!(:field_format => 'float', :is_for_all => true)
1234 field = IssueCustomField.generate!(:field_format => 'float', :is_for_all => true)
1233 q = IssueQuery.new
1235 q = IssueQuery.new
1234 assert_include "cf_#{field.id}".to_sym, q.available_totalable_columns.map(&:name)
1236 assert_include "cf_#{field.id}".to_sym, q.available_totalable_columns.map(&:name)
1235 end
1237 end
1236
1238
1237 def test_total_for_estimated_hours
1239 def test_total_for_estimated_hours
1238 Issue.delete_all
1240 Issue.delete_all
1239 Issue.generate!(:estimated_hours => 5.5)
1241 Issue.generate!(:estimated_hours => 5.5)
1240 Issue.generate!(:estimated_hours => 1.1)
1242 Issue.generate!(:estimated_hours => 1.1)
1241 Issue.generate!
1243 Issue.generate!
1242
1244
1243 q = IssueQuery.new
1245 q = IssueQuery.new
1244 assert_equal 6.6, q.total_for(:estimated_hours)
1246 assert_equal 6.6, q.total_for(:estimated_hours)
1245 end
1247 end
1246
1248
1247 def test_total_by_group_for_estimated_hours
1249 def test_total_by_group_for_estimated_hours
1248 Issue.delete_all
1250 Issue.delete_all
1249 Issue.generate!(:estimated_hours => 5.5, :assigned_to_id => 2)
1251 Issue.generate!(:estimated_hours => 5.5, :assigned_to_id => 2)
1250 Issue.generate!(:estimated_hours => 1.1, :assigned_to_id => 3)
1252 Issue.generate!(:estimated_hours => 1.1, :assigned_to_id => 3)
1251 Issue.generate!(:estimated_hours => 3.5)
1253 Issue.generate!(:estimated_hours => 3.5)
1252
1254
1253 q = IssueQuery.new(:group_by => 'assigned_to')
1255 q = IssueQuery.new(:group_by => 'assigned_to')
1254 assert_equal(
1256 assert_equal(
1255 {nil => 3.5, User.find(2) => 5.5, User.find(3) => 1.1},
1257 {nil => 3.5, User.find(2) => 5.5, User.find(3) => 1.1},
1256 q.total_by_group_for(:estimated_hours)
1258 q.total_by_group_for(:estimated_hours)
1257 )
1259 )
1258 end
1260 end
1259
1261
1260 def test_total_for_spent_hours
1262 def test_total_for_spent_hours
1261 TimeEntry.delete_all
1263 TimeEntry.delete_all
1262 TimeEntry.generate!(:hours => 5.5)
1264 TimeEntry.generate!(:hours => 5.5)
1263 TimeEntry.generate!(:hours => 1.1)
1265 TimeEntry.generate!(:hours => 1.1)
1264
1266
1265 q = IssueQuery.new
1267 q = IssueQuery.new
1266 assert_equal 6.6, q.total_for(:spent_hours)
1268 assert_equal 6.6, q.total_for(:spent_hours)
1267 end
1269 end
1268
1270
1269 def test_total_by_group_for_spent_hours
1271 def test_total_by_group_for_spent_hours
1270 TimeEntry.delete_all
1272 TimeEntry.delete_all
1271 TimeEntry.generate!(:hours => 5.5, :issue_id => 1)
1273 TimeEntry.generate!(:hours => 5.5, :issue_id => 1)
1272 TimeEntry.generate!(:hours => 1.1, :issue_id => 2)
1274 TimeEntry.generate!(:hours => 1.1, :issue_id => 2)
1273 Issue.where(:id => 1).update_all(:assigned_to_id => 2)
1275 Issue.where(:id => 1).update_all(:assigned_to_id => 2)
1274 Issue.where(:id => 2).update_all(:assigned_to_id => 3)
1276 Issue.where(:id => 2).update_all(:assigned_to_id => 3)
1275
1277
1276 q = IssueQuery.new(:group_by => 'assigned_to')
1278 q = IssueQuery.new(:group_by => 'assigned_to')
1277 assert_equal(
1279 assert_equal(
1278 {User.find(2) => 5.5, User.find(3) => 1.1},
1280 {User.find(2) => 5.5, User.find(3) => 1.1},
1279 q.total_by_group_for(:spent_hours)
1281 q.total_by_group_for(:spent_hours)
1280 )
1282 )
1281 end
1283 end
1282
1284
1283 def test_total_by_project_group_for_spent_hours
1285 def test_total_by_project_group_for_spent_hours
1284 TimeEntry.delete_all
1286 TimeEntry.delete_all
1285 TimeEntry.generate!(:hours => 5.5, :issue_id => 1)
1287 TimeEntry.generate!(:hours => 5.5, :issue_id => 1)
1286 TimeEntry.generate!(:hours => 1.1, :issue_id => 2)
1288 TimeEntry.generate!(:hours => 1.1, :issue_id => 2)
1287 Issue.where(:id => 1).update_all(:assigned_to_id => 2)
1289 Issue.where(:id => 1).update_all(:assigned_to_id => 2)
1288 Issue.where(:id => 2).update_all(:assigned_to_id => 3)
1290 Issue.where(:id => 2).update_all(:assigned_to_id => 3)
1289
1291
1290 q = IssueQuery.new(:group_by => 'project')
1292 q = IssueQuery.new(:group_by => 'project')
1291 assert_equal(
1293 assert_equal(
1292 {Project.find(1) => 6.6},
1294 {Project.find(1) => 6.6},
1293 q.total_by_group_for(:spent_hours)
1295 q.total_by_group_for(:spent_hours)
1294 )
1296 )
1295 end
1297 end
1296
1298
1297 def test_total_for_int_custom_field
1299 def test_total_for_int_custom_field
1298 field = IssueCustomField.generate!(:field_format => 'int', :is_for_all => true)
1300 field = IssueCustomField.generate!(:field_format => 'int', :is_for_all => true)
1299 CustomValue.create!(:customized => Issue.find(1), :custom_field => field, :value => '2')
1301 CustomValue.create!(:customized => Issue.find(1), :custom_field => field, :value => '2')
1300 CustomValue.create!(:customized => Issue.find(2), :custom_field => field, :value => '7')
1302 CustomValue.create!(:customized => Issue.find(2), :custom_field => field, :value => '7')
1301 CustomValue.create!(:customized => Issue.find(3), :custom_field => field, :value => '')
1303 CustomValue.create!(:customized => Issue.find(3), :custom_field => field, :value => '')
1302
1304
1303 q = IssueQuery.new
1305 q = IssueQuery.new
1304 assert_equal 9, q.total_for("cf_#{field.id}")
1306 assert_equal 9, q.total_for("cf_#{field.id}")
1305 end
1307 end
1306
1308
1307 def test_total_by_group_for_int_custom_field
1309 def test_total_by_group_for_int_custom_field
1308 field = IssueCustomField.generate!(:field_format => 'int', :is_for_all => true)
1310 field = IssueCustomField.generate!(:field_format => 'int', :is_for_all => true)
1309 CustomValue.create!(:customized => Issue.find(1), :custom_field => field, :value => '2')
1311 CustomValue.create!(:customized => Issue.find(1), :custom_field => field, :value => '2')
1310 CustomValue.create!(:customized => Issue.find(2), :custom_field => field, :value => '7')
1312 CustomValue.create!(:customized => Issue.find(2), :custom_field => field, :value => '7')
1311 Issue.where(:id => 1).update_all(:assigned_to_id => 2)
1313 Issue.where(:id => 1).update_all(:assigned_to_id => 2)
1312 Issue.where(:id => 2).update_all(:assigned_to_id => 3)
1314 Issue.where(:id => 2).update_all(:assigned_to_id => 3)
1313
1315
1314 q = IssueQuery.new(:group_by => 'assigned_to')
1316 q = IssueQuery.new(:group_by => 'assigned_to')
1315 assert_equal(
1317 assert_equal(
1316 {User.find(2) => 2, User.find(3) => 7},
1318 {User.find(2) => 2, User.find(3) => 7},
1317 q.total_by_group_for("cf_#{field.id}")
1319 q.total_by_group_for("cf_#{field.id}")
1318 )
1320 )
1319 end
1321 end
1320
1322
1321 def test_total_for_float_custom_field
1323 def test_total_for_float_custom_field
1322 field = IssueCustomField.generate!(:field_format => 'float', :is_for_all => true)
1324 field = IssueCustomField.generate!(:field_format => 'float', :is_for_all => true)
1323 CustomValue.create!(:customized => Issue.find(1), :custom_field => field, :value => '2.3')
1325 CustomValue.create!(:customized => Issue.find(1), :custom_field => field, :value => '2.3')
1324 CustomValue.create!(:customized => Issue.find(2), :custom_field => field, :value => '7')
1326 CustomValue.create!(:customized => Issue.find(2), :custom_field => field, :value => '7')
1325 CustomValue.create!(:customized => Issue.find(3), :custom_field => field, :value => '')
1327 CustomValue.create!(:customized => Issue.find(3), :custom_field => field, :value => '')
1326
1328
1327 q = IssueQuery.new
1329 q = IssueQuery.new
1328 assert_equal 9.3, q.total_for("cf_#{field.id}")
1330 assert_equal 9.3, q.total_for("cf_#{field.id}")
1329 end
1331 end
1330
1332
1331 def test_invalid_query_should_raise_query_statement_invalid_error
1333 def test_invalid_query_should_raise_query_statement_invalid_error
1332 q = IssueQuery.new
1334 q = IssueQuery.new
1333 assert_raise Query::StatementInvalid do
1335 assert_raise Query::StatementInvalid do
1334 q.issues(:conditions => "foo = 1")
1336 q.issues(:conditions => "foo = 1")
1335 end
1337 end
1336 end
1338 end
1337
1339
1338 def test_issue_count
1340 def test_issue_count
1339 q = IssueQuery.new(:name => '_')
1341 q = IssueQuery.new(:name => '_')
1340 issue_count = q.issue_count
1342 issue_count = q.issue_count
1341 assert_equal q.issues.size, issue_count
1343 assert_equal q.issues.size, issue_count
1342 end
1344 end
1343
1345
1344 def test_issue_count_with_archived_issues
1346 def test_issue_count_with_archived_issues
1345 p = Project.generate! do |project|
1347 p = Project.generate! do |project|
1346 project.status = Project::STATUS_ARCHIVED
1348 project.status = Project::STATUS_ARCHIVED
1347 end
1349 end
1348 i = Issue.generate!( :project => p, :tracker => p.trackers.first )
1350 i = Issue.generate!( :project => p, :tracker => p.trackers.first )
1349 assert !i.visible?
1351 assert !i.visible?
1350
1352
1351 test_issue_count
1353 test_issue_count
1352 end
1354 end
1353
1355
1354 def test_issue_count_by_association_group
1356 def test_issue_count_by_association_group
1355 q = IssueQuery.new(:name => '_', :group_by => 'assigned_to')
1357 q = IssueQuery.new(:name => '_', :group_by => 'assigned_to')
1356 count_by_group = q.issue_count_by_group
1358 count_by_group = q.issue_count_by_group
1357 assert_kind_of Hash, count_by_group
1359 assert_kind_of Hash, count_by_group
1358 assert_equal %w(NilClass User), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
1360 assert_equal %w(NilClass User), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
1359 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
1361 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
1360 assert count_by_group.has_key?(User.find(3))
1362 assert count_by_group.has_key?(User.find(3))
1361 end
1363 end
1362
1364
1363 def test_issue_count_by_list_custom_field_group
1365 def test_issue_count_by_list_custom_field_group
1364 q = IssueQuery.new(:name => '_', :group_by => 'cf_1')
1366 q = IssueQuery.new(:name => '_', :group_by => 'cf_1')
1365 count_by_group = q.issue_count_by_group
1367 count_by_group = q.issue_count_by_group
1366 assert_kind_of Hash, count_by_group
1368 assert_kind_of Hash, count_by_group
1367 assert_equal %w(NilClass String), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
1369 assert_equal %w(NilClass String), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
1368 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
1370 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
1369 assert count_by_group.has_key?('MySQL')
1371 assert count_by_group.has_key?('MySQL')
1370 end
1372 end
1371
1373
1372 def test_issue_count_by_date_custom_field_group
1374 def test_issue_count_by_date_custom_field_group
1373 q = IssueQuery.new(:name => '_', :group_by => 'cf_8')
1375 q = IssueQuery.new(:name => '_', :group_by => 'cf_8')
1374 count_by_group = q.issue_count_by_group
1376 count_by_group = q.issue_count_by_group
1375 assert_kind_of Hash, count_by_group
1377 assert_kind_of Hash, count_by_group
1376 assert_equal %w(Date NilClass), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
1378 assert_equal %w(Date NilClass), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
1377 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
1379 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
1378 end
1380 end
1379
1381
1380 def test_issue_count_with_nil_group_only
1382 def test_issue_count_with_nil_group_only
1381 Issue.update_all("assigned_to_id = NULL")
1383 Issue.update_all("assigned_to_id = NULL")
1382
1384
1383 q = IssueQuery.new(:name => '_', :group_by => 'assigned_to')
1385 q = IssueQuery.new(:name => '_', :group_by => 'assigned_to')
1384 count_by_group = q.issue_count_by_group
1386 count_by_group = q.issue_count_by_group
1385 assert_kind_of Hash, count_by_group
1387 assert_kind_of Hash, count_by_group
1386 assert_equal 1, count_by_group.keys.size
1388 assert_equal 1, count_by_group.keys.size
1387 assert_nil count_by_group.keys.first
1389 assert_nil count_by_group.keys.first
1388 end
1390 end
1389
1391
1390 def test_issue_ids
1392 def test_issue_ids
1391 q = IssueQuery.new(:name => '_')
1393 q = IssueQuery.new(:name => '_')
1392 order = "issues.subject, issues.id"
1394 order = "issues.subject, issues.id"
1393 issues = q.issues(:order => order)
1395 issues = q.issues(:order => order)
1394 assert_equal issues.map(&:id), q.issue_ids(:order => order)
1396 assert_equal issues.map(&:id), q.issue_ids(:order => order)
1395 end
1397 end
1396
1398
1397 def test_label_for
1399 def test_label_for
1398 set_language_if_valid 'en'
1400 set_language_if_valid 'en'
1399 q = IssueQuery.new
1401 q = IssueQuery.new
1400 assert_equal 'Assignee', q.label_for('assigned_to_id')
1402 assert_equal 'Assignee', q.label_for('assigned_to_id')
1401 end
1403 end
1402
1404
1403 def test_label_for_fr
1405 def test_label_for_fr
1404 set_language_if_valid 'fr'
1406 set_language_if_valid 'fr'
1405 q = IssueQuery.new
1407 q = IssueQuery.new
1406 assert_equal "Assign\xc3\xa9 \xc3\xa0".force_encoding('UTF-8'), q.label_for('assigned_to_id')
1408 assert_equal "Assign\xc3\xa9 \xc3\xa0".force_encoding('UTF-8'), q.label_for('assigned_to_id')
1407 end
1409 end
1408
1410
1409 def test_editable_by
1411 def test_editable_by
1410 admin = User.find(1)
1412 admin = User.find(1)
1411 manager = User.find(2)
1413 manager = User.find(2)
1412 developer = User.find(3)
1414 developer = User.find(3)
1413
1415
1414 # Public query on project 1
1416 # Public query on project 1
1415 q = IssueQuery.find(1)
1417 q = IssueQuery.find(1)
1416 assert q.editable_by?(admin)
1418 assert q.editable_by?(admin)
1417 assert q.editable_by?(manager)
1419 assert q.editable_by?(manager)
1418 assert !q.editable_by?(developer)
1420 assert !q.editable_by?(developer)
1419
1421
1420 # Private query on project 1
1422 # Private query on project 1
1421 q = IssueQuery.find(2)
1423 q = IssueQuery.find(2)
1422 assert q.editable_by?(admin)
1424 assert q.editable_by?(admin)
1423 assert !q.editable_by?(manager)
1425 assert !q.editable_by?(manager)
1424 assert q.editable_by?(developer)
1426 assert q.editable_by?(developer)
1425
1427
1426 # Private query for all projects
1428 # Private query for all projects
1427 q = IssueQuery.find(3)
1429 q = IssueQuery.find(3)
1428 assert q.editable_by?(admin)
1430 assert q.editable_by?(admin)
1429 assert !q.editable_by?(manager)
1431 assert !q.editable_by?(manager)
1430 assert q.editable_by?(developer)
1432 assert q.editable_by?(developer)
1431
1433
1432 # Public query for all projects
1434 # Public query for all projects
1433 q = IssueQuery.find(4)
1435 q = IssueQuery.find(4)
1434 assert q.editable_by?(admin)
1436 assert q.editable_by?(admin)
1435 assert !q.editable_by?(manager)
1437 assert !q.editable_by?(manager)
1436 assert !q.editable_by?(developer)
1438 assert !q.editable_by?(developer)
1437 end
1439 end
1438
1440
1439 def test_visible_scope
1441 def test_visible_scope
1440 query_ids = IssueQuery.visible(User.anonymous).map(&:id)
1442 query_ids = IssueQuery.visible(User.anonymous).map(&:id)
1441
1443
1442 assert query_ids.include?(1), 'public query on public project was not visible'
1444 assert query_ids.include?(1), 'public query on public project was not visible'
1443 assert query_ids.include?(4), 'public query for all projects was not visible'
1445 assert query_ids.include?(4), 'public query for all projects was not visible'
1444 assert !query_ids.include?(2), 'private query on public project was visible'
1446 assert !query_ids.include?(2), 'private query on public project was visible'
1445 assert !query_ids.include?(3), 'private query for all projects was visible'
1447 assert !query_ids.include?(3), 'private query for all projects was visible'
1446 assert !query_ids.include?(7), 'public query on private project was visible'
1448 assert !query_ids.include?(7), 'public query on private project was visible'
1447 end
1449 end
1448
1450
1449 def test_query_with_public_visibility_should_be_visible_to_anyone
1451 def test_query_with_public_visibility_should_be_visible_to_anyone
1450 q = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_PUBLIC)
1452 q = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_PUBLIC)
1451
1453
1452 assert q.visible?(User.anonymous)
1454 assert q.visible?(User.anonymous)
1453 assert IssueQuery.visible(User.anonymous).find_by_id(q.id)
1455 assert IssueQuery.visible(User.anonymous).find_by_id(q.id)
1454
1456
1455 assert q.visible?(User.find(7))
1457 assert q.visible?(User.find(7))
1456 assert IssueQuery.visible(User.find(7)).find_by_id(q.id)
1458 assert IssueQuery.visible(User.find(7)).find_by_id(q.id)
1457
1459
1458 assert q.visible?(User.find(2))
1460 assert q.visible?(User.find(2))
1459 assert IssueQuery.visible(User.find(2)).find_by_id(q.id)
1461 assert IssueQuery.visible(User.find(2)).find_by_id(q.id)
1460
1462
1461 assert q.visible?(User.find(1))
1463 assert q.visible?(User.find(1))
1462 assert IssueQuery.visible(User.find(1)).find_by_id(q.id)
1464 assert IssueQuery.visible(User.find(1)).find_by_id(q.id)
1463 end
1465 end
1464
1466
1465 def test_query_with_roles_visibility_should_be_visible_to_user_with_role
1467 def test_query_with_roles_visibility_should_be_visible_to_user_with_role
1466 q = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_ROLES, :role_ids => [1,2])
1468 q = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_ROLES, :role_ids => [1,2])
1467
1469
1468 assert !q.visible?(User.anonymous)
1470 assert !q.visible?(User.anonymous)
1469 assert_nil IssueQuery.visible(User.anonymous).find_by_id(q.id)
1471 assert_nil IssueQuery.visible(User.anonymous).find_by_id(q.id)
1470
1472
1471 assert !q.visible?(User.find(7))
1473 assert !q.visible?(User.find(7))
1472 assert_nil IssueQuery.visible(User.find(7)).find_by_id(q.id)
1474 assert_nil IssueQuery.visible(User.find(7)).find_by_id(q.id)
1473
1475
1474 assert q.visible?(User.find(2))
1476 assert q.visible?(User.find(2))
1475 assert IssueQuery.visible(User.find(2)).find_by_id(q.id)
1477 assert IssueQuery.visible(User.find(2)).find_by_id(q.id)
1476
1478
1477 assert q.visible?(User.find(1))
1479 assert q.visible?(User.find(1))
1478 assert IssueQuery.visible(User.find(1)).find_by_id(q.id)
1480 assert IssueQuery.visible(User.find(1)).find_by_id(q.id)
1479 end
1481 end
1480
1482
1481 def test_query_with_private_visibility_should_be_visible_to_owner
1483 def test_query_with_private_visibility_should_be_visible_to_owner
1482 q = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_PRIVATE, :user => User.find(7))
1484 q = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_PRIVATE, :user => User.find(7))
1483
1485
1484 assert !q.visible?(User.anonymous)
1486 assert !q.visible?(User.anonymous)
1485 assert_nil IssueQuery.visible(User.anonymous).find_by_id(q.id)
1487 assert_nil IssueQuery.visible(User.anonymous).find_by_id(q.id)
1486
1488
1487 assert q.visible?(User.find(7))
1489 assert q.visible?(User.find(7))
1488 assert IssueQuery.visible(User.find(7)).find_by_id(q.id)
1490 assert IssueQuery.visible(User.find(7)).find_by_id(q.id)
1489
1491
1490 assert !q.visible?(User.find(2))
1492 assert !q.visible?(User.find(2))
1491 assert_nil IssueQuery.visible(User.find(2)).find_by_id(q.id)
1493 assert_nil IssueQuery.visible(User.find(2)).find_by_id(q.id)
1492
1494
1493 assert q.visible?(User.find(1))
1495 assert q.visible?(User.find(1))
1494 assert_nil IssueQuery.visible(User.find(1)).find_by_id(q.id)
1496 assert_nil IssueQuery.visible(User.find(1)).find_by_id(q.id)
1495 end
1497 end
1496
1498
1497 test "#available_filters should include users of visible projects in cross-project view" do
1499 test "#available_filters should include users of visible projects in cross-project view" do
1498 users = IssueQuery.new.available_filters["assigned_to_id"]
1500 users = IssueQuery.new.available_filters["assigned_to_id"]
1499 assert_not_nil users
1501 assert_not_nil users
1500 assert users[:values].map{|u|u[1]}.include?("3")
1502 assert users[:values].map{|u|u[1]}.include?("3")
1501 end
1503 end
1502
1504
1503 test "#available_filters should include users of subprojects" do
1505 test "#available_filters should include users of subprojects" do
1504 user1 = User.generate!
1506 user1 = User.generate!
1505 user2 = User.generate!
1507 user2 = User.generate!
1506 project = Project.find(1)
1508 project = Project.find(1)
1507 Member.create!(:principal => user1, :project => project.children.visible.first, :role_ids => [1])
1509 Member.create!(:principal => user1, :project => project.children.visible.first, :role_ids => [1])
1508
1510
1509 users = IssueQuery.new(:project => project).available_filters["assigned_to_id"]
1511 users = IssueQuery.new(:project => project).available_filters["assigned_to_id"]
1510 assert_not_nil users
1512 assert_not_nil users
1511 assert users[:values].map{|u|u[1]}.include?(user1.id.to_s)
1513 assert users[:values].map{|u|u[1]}.include?(user1.id.to_s)
1512 assert !users[:values].map{|u|u[1]}.include?(user2.id.to_s)
1514 assert !users[:values].map{|u|u[1]}.include?(user2.id.to_s)
1513 end
1515 end
1514
1516
1515 test "#available_filters should include visible projects in cross-project view" do
1517 test "#available_filters should include visible projects in cross-project view" do
1516 projects = IssueQuery.new.available_filters["project_id"]
1518 projects = IssueQuery.new.available_filters["project_id"]
1517 assert_not_nil projects
1519 assert_not_nil projects
1518 assert projects[:values].map{|u|u[1]}.include?("1")
1520 assert projects[:values].map{|u|u[1]}.include?("1")
1519 end
1521 end
1520
1522
1521 test "#available_filters should include 'member_of_group' filter" do
1523 test "#available_filters should include 'member_of_group' filter" do
1522 query = IssueQuery.new
1524 query = IssueQuery.new
1523 assert query.available_filters.keys.include?("member_of_group")
1525 assert query.available_filters.keys.include?("member_of_group")
1524 assert_equal :list_optional, query.available_filters["member_of_group"][:type]
1526 assert_equal :list_optional, query.available_filters["member_of_group"][:type]
1525 assert query.available_filters["member_of_group"][:values].present?
1527 assert query.available_filters["member_of_group"][:values].present?
1526 assert_equal Group.givable.sort.map {|g| [g.name, g.id.to_s]},
1528 assert_equal Group.givable.sort.map {|g| [g.name, g.id.to_s]},
1527 query.available_filters["member_of_group"][:values].sort
1529 query.available_filters["member_of_group"][:values].sort
1528 end
1530 end
1529
1531
1530 test "#available_filters should include 'assigned_to_role' filter" do
1532 test "#available_filters should include 'assigned_to_role' filter" do
1531 query = IssueQuery.new
1533 query = IssueQuery.new
1532 assert query.available_filters.keys.include?("assigned_to_role")
1534 assert query.available_filters.keys.include?("assigned_to_role")
1533 assert_equal :list_optional, query.available_filters["assigned_to_role"][:type]
1535 assert_equal :list_optional, query.available_filters["assigned_to_role"][:type]
1534
1536
1535 assert query.available_filters["assigned_to_role"][:values].include?(['Manager','1'])
1537 assert query.available_filters["assigned_to_role"][:values].include?(['Manager','1'])
1536 assert query.available_filters["assigned_to_role"][:values].include?(['Developer','2'])
1538 assert query.available_filters["assigned_to_role"][:values].include?(['Developer','2'])
1537 assert query.available_filters["assigned_to_role"][:values].include?(['Reporter','3'])
1539 assert query.available_filters["assigned_to_role"][:values].include?(['Reporter','3'])
1538
1540
1539 assert ! query.available_filters["assigned_to_role"][:values].include?(['Non member','4'])
1541 assert ! query.available_filters["assigned_to_role"][:values].include?(['Non member','4'])
1540 assert ! query.available_filters["assigned_to_role"][:values].include?(['Anonymous','5'])
1542 assert ! query.available_filters["assigned_to_role"][:values].include?(['Anonymous','5'])
1541 end
1543 end
1542
1544
1543 def test_available_filters_should_include_custom_field_according_to_user_visibility
1545 def test_available_filters_should_include_custom_field_according_to_user_visibility
1544 visible_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => true)
1546 visible_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => true)
1545 hidden_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => false, :role_ids => [1])
1547 hidden_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => false, :role_ids => [1])
1546
1548
1547 with_current_user User.find(3) do
1549 with_current_user User.find(3) do
1548 query = IssueQuery.new
1550 query = IssueQuery.new
1549 assert_include "cf_#{visible_field.id}", query.available_filters.keys
1551 assert_include "cf_#{visible_field.id}", query.available_filters.keys
1550 assert_not_include "cf_#{hidden_field.id}", query.available_filters.keys
1552 assert_not_include "cf_#{hidden_field.id}", query.available_filters.keys
1551 end
1553 end
1552 end
1554 end
1553
1555
1554 def test_available_columns_should_include_custom_field_according_to_user_visibility
1556 def test_available_columns_should_include_custom_field_according_to_user_visibility
1555 visible_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => true)
1557 visible_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => true)
1556 hidden_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => false, :role_ids => [1])
1558 hidden_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => false, :role_ids => [1])
1557
1559
1558 with_current_user User.find(3) do
1560 with_current_user User.find(3) do
1559 query = IssueQuery.new
1561 query = IssueQuery.new
1560 assert_include :"cf_#{visible_field.id}", query.available_columns.map(&:name)
1562 assert_include :"cf_#{visible_field.id}", query.available_columns.map(&:name)
1561 assert_not_include :"cf_#{hidden_field.id}", query.available_columns.map(&:name)
1563 assert_not_include :"cf_#{hidden_field.id}", query.available_columns.map(&:name)
1562 end
1564 end
1563 end
1565 end
1564
1566
1565 def setup_member_of_group
1567 def setup_member_of_group
1566 Group.destroy_all # No fixtures
1568 Group.destroy_all # No fixtures
1567 @user_in_group = User.generate!
1569 @user_in_group = User.generate!
1568 @second_user_in_group = User.generate!
1570 @second_user_in_group = User.generate!
1569 @user_in_group2 = User.generate!
1571 @user_in_group2 = User.generate!
1570 @user_not_in_group = User.generate!
1572 @user_not_in_group = User.generate!
1571
1573
1572 @group = Group.generate!.reload
1574 @group = Group.generate!.reload
1573 @group.users << @user_in_group
1575 @group.users << @user_in_group
1574 @group.users << @second_user_in_group
1576 @group.users << @second_user_in_group
1575
1577
1576 @group2 = Group.generate!.reload
1578 @group2 = Group.generate!.reload
1577 @group2.users << @user_in_group2
1579 @group2.users << @user_in_group2
1578
1580
1579 @query = IssueQuery.new(:name => '_')
1581 @query = IssueQuery.new(:name => '_')
1580 end
1582 end
1581
1583
1582 test "member_of_group filter should search assigned to for users in the group" do
1584 test "member_of_group filter should search assigned to for users in the group" do
1583 setup_member_of_group
1585 setup_member_of_group
1584 @query.add_filter('member_of_group', '=', [@group.id.to_s])
1586 @query.add_filter('member_of_group', '=', [@group.id.to_s])
1585
1587
1586 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@user_in_group.id}','#{@second_user_in_group.id}','#{@group.id}')"
1588 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@user_in_group.id}','#{@second_user_in_group.id}','#{@group.id}')"
1587 assert_find_issues_with_query_is_successful @query
1589 assert_find_issues_with_query_is_successful @query
1588 end
1590 end
1589
1591
1590 test "member_of_group filter should search not assigned to any group member (none)" do
1592 test "member_of_group filter should search not assigned to any group member (none)" do
1591 setup_member_of_group
1593 setup_member_of_group
1592 @query.add_filter('member_of_group', '!*', [''])
1594 @query.add_filter('member_of_group', '!*', [''])
1593
1595
1594 # Users not in a group
1596 # Users not in a group
1595 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}')"
1597 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}')"
1596 assert_find_issues_with_query_is_successful @query
1598 assert_find_issues_with_query_is_successful @query
1597 end
1599 end
1598
1600
1599 test "member_of_group filter should search assigned to any group member (all)" do
1601 test "member_of_group filter should search assigned to any group member (all)" do
1600 setup_member_of_group
1602 setup_member_of_group
1601 @query.add_filter('member_of_group', '*', [''])
1603 @query.add_filter('member_of_group', '*', [''])
1602
1604
1603 # Only users in a group
1605 # Only users in a group
1604 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}')"
1606 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}')"
1605 assert_find_issues_with_query_is_successful @query
1607 assert_find_issues_with_query_is_successful @query
1606 end
1608 end
1607
1609
1608 test "member_of_group filter should return an empty set with = empty group" do
1610 test "member_of_group filter should return an empty set with = empty group" do
1609 setup_member_of_group
1611 setup_member_of_group
1610 @empty_group = Group.generate!
1612 @empty_group = Group.generate!
1611 @query.add_filter('member_of_group', '=', [@empty_group.id.to_s])
1613 @query.add_filter('member_of_group', '=', [@empty_group.id.to_s])
1612
1614
1613 assert_equal [], find_issues_with_query(@query)
1615 assert_equal [], find_issues_with_query(@query)
1614 end
1616 end
1615
1617
1616 test "member_of_group filter should return issues with ! empty group" do
1618 test "member_of_group filter should return issues with ! empty group" do
1617 setup_member_of_group
1619 setup_member_of_group
1618 @empty_group = Group.generate!
1620 @empty_group = Group.generate!
1619 @query.add_filter('member_of_group', '!', [@empty_group.id.to_s])
1621 @query.add_filter('member_of_group', '!', [@empty_group.id.to_s])
1620
1622
1621 assert_find_issues_with_query_is_successful @query
1623 assert_find_issues_with_query_is_successful @query
1622 end
1624 end
1623
1625
1624 def setup_assigned_to_role
1626 def setup_assigned_to_role
1625 @manager_role = Role.find_by_name('Manager')
1627 @manager_role = Role.find_by_name('Manager')
1626 @developer_role = Role.find_by_name('Developer')
1628 @developer_role = Role.find_by_name('Developer')
1627
1629
1628 @project = Project.generate!
1630 @project = Project.generate!
1629 @manager = User.generate!
1631 @manager = User.generate!
1630 @developer = User.generate!
1632 @developer = User.generate!
1631 @boss = User.generate!
1633 @boss = User.generate!
1632 @guest = User.generate!
1634 @guest = User.generate!
1633 User.add_to_project(@manager, @project, @manager_role)
1635 User.add_to_project(@manager, @project, @manager_role)
1634 User.add_to_project(@developer, @project, @developer_role)
1636 User.add_to_project(@developer, @project, @developer_role)
1635 User.add_to_project(@boss, @project, [@manager_role, @developer_role])
1637 User.add_to_project(@boss, @project, [@manager_role, @developer_role])
1636
1638
1637 @issue1 = Issue.generate!(:project => @project, :assigned_to_id => @manager.id)
1639 @issue1 = Issue.generate!(:project => @project, :assigned_to_id => @manager.id)
1638 @issue2 = Issue.generate!(:project => @project, :assigned_to_id => @developer.id)
1640 @issue2 = Issue.generate!(:project => @project, :assigned_to_id => @developer.id)
1639 @issue3 = Issue.generate!(:project => @project, :assigned_to_id => @boss.id)
1641 @issue3 = Issue.generate!(:project => @project, :assigned_to_id => @boss.id)
1640 @issue4 = Issue.generate!(:project => @project, :assigned_to_id => @guest.id)
1642 @issue4 = Issue.generate!(:project => @project, :assigned_to_id => @guest.id)
1641 @issue5 = Issue.generate!(:project => @project)
1643 @issue5 = Issue.generate!(:project => @project)
1642
1644
1643 @query = IssueQuery.new(:name => '_', :project => @project)
1645 @query = IssueQuery.new(:name => '_', :project => @project)
1644 end
1646 end
1645
1647
1646 test "assigned_to_role filter should search assigned to for users with the Role" do
1648 test "assigned_to_role filter should search assigned to for users with the Role" do
1647 setup_assigned_to_role
1649 setup_assigned_to_role
1648 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
1650 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
1649
1651
1650 assert_query_result [@issue1, @issue3], @query
1652 assert_query_result [@issue1, @issue3], @query
1651 end
1653 end
1652
1654
1653 test "assigned_to_role filter should search assigned to for users with the Role on the issue project" do
1655 test "assigned_to_role filter should search assigned to for users with the Role on the issue project" do
1654 setup_assigned_to_role
1656 setup_assigned_to_role
1655 other_project = Project.generate!
1657 other_project = Project.generate!
1656 User.add_to_project(@developer, other_project, @manager_role)
1658 User.add_to_project(@developer, other_project, @manager_role)
1657 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
1659 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
1658
1660
1659 assert_query_result [@issue1, @issue3], @query
1661 assert_query_result [@issue1, @issue3], @query
1660 end
1662 end
1661
1663
1662 test "assigned_to_role filter should return an empty set with empty role" do
1664 test "assigned_to_role filter should return an empty set with empty role" do
1663 setup_assigned_to_role
1665 setup_assigned_to_role
1664 @empty_role = Role.generate!
1666 @empty_role = Role.generate!
1665 @query.add_filter('assigned_to_role', '=', [@empty_role.id.to_s])
1667 @query.add_filter('assigned_to_role', '=', [@empty_role.id.to_s])
1666
1668
1667 assert_query_result [], @query
1669 assert_query_result [], @query
1668 end
1670 end
1669
1671
1670 test "assigned_to_role filter should search assigned to for users without the Role" do
1672 test "assigned_to_role filter should search assigned to for users without the Role" do
1671 setup_assigned_to_role
1673 setup_assigned_to_role
1672 @query.add_filter('assigned_to_role', '!', [@manager_role.id.to_s])
1674 @query.add_filter('assigned_to_role', '!', [@manager_role.id.to_s])
1673
1675
1674 assert_query_result [@issue2, @issue4, @issue5], @query
1676 assert_query_result [@issue2, @issue4, @issue5], @query
1675 end
1677 end
1676
1678
1677 test "assigned_to_role filter should search assigned to for users not assigned to any Role (none)" do
1679 test "assigned_to_role filter should search assigned to for users not assigned to any Role (none)" do
1678 setup_assigned_to_role
1680 setup_assigned_to_role
1679 @query.add_filter('assigned_to_role', '!*', [''])
1681 @query.add_filter('assigned_to_role', '!*', [''])
1680
1682
1681 assert_query_result [@issue4, @issue5], @query
1683 assert_query_result [@issue4, @issue5], @query
1682 end
1684 end
1683
1685
1684 test "assigned_to_role filter should search assigned to for users assigned to any Role (all)" do
1686 test "assigned_to_role filter should search assigned to for users assigned to any Role (all)" do
1685 setup_assigned_to_role
1687 setup_assigned_to_role
1686 @query.add_filter('assigned_to_role', '*', [''])
1688 @query.add_filter('assigned_to_role', '*', [''])
1687
1689
1688 assert_query_result [@issue1, @issue2, @issue3], @query
1690 assert_query_result [@issue1, @issue2, @issue3], @query
1689 end
1691 end
1690
1692
1691 test "assigned_to_role filter should return issues with ! empty role" do
1693 test "assigned_to_role filter should return issues with ! empty role" do
1692 setup_assigned_to_role
1694 setup_assigned_to_role
1693 @empty_role = Role.generate!
1695 @empty_role = Role.generate!
1694 @query.add_filter('assigned_to_role', '!', [@empty_role.id.to_s])
1696 @query.add_filter('assigned_to_role', '!', [@empty_role.id.to_s])
1695
1697
1696 assert_query_result [@issue1, @issue2, @issue3, @issue4, @issue5], @query
1698 assert_query_result [@issue1, @issue2, @issue3, @issue4, @issue5], @query
1697 end
1699 end
1698
1700
1699 def test_query_column_should_accept_a_symbol_as_caption
1701 def test_query_column_should_accept_a_symbol_as_caption
1700 set_language_if_valid 'en'
1702 set_language_if_valid 'en'
1701 c = QueryColumn.new('foo', :caption => :general_text_Yes)
1703 c = QueryColumn.new('foo', :caption => :general_text_Yes)
1702 assert_equal 'Yes', c.caption
1704 assert_equal 'Yes', c.caption
1703 end
1705 end
1704
1706
1705 def test_query_column_should_accept_a_proc_as_caption
1707 def test_query_column_should_accept_a_proc_as_caption
1706 c = QueryColumn.new('foo', :caption => lambda {'Foo'})
1708 c = QueryColumn.new('foo', :caption => lambda {'Foo'})
1707 assert_equal 'Foo', c.caption
1709 assert_equal 'Foo', c.caption
1708 end
1710 end
1709 end
1711 end
General Comments 0
You need to be logged in to leave comments. Login now