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