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