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