##// END OF EJS Templates
Merged r10249 from trunk to 1.4-stable...
Toshi MARUYAMA -
r10077:231145160f88
parent child
Show More
@@ -1,1019 +1,1022
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 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
22
21 fixtures :projects, :enabled_modules, :users, :members,
23 fixtures :projects, :enabled_modules, :users, :members,
22 :member_roles, :roles, :trackers, :issue_statuses,
24 :member_roles, :roles, :trackers, :issue_statuses,
23 :issue_categories, :enumerations, :issues,
25 :issue_categories, :enumerations, :issues,
24 :watchers, :custom_fields, :custom_values, :versions,
26 :watchers, :custom_fields, :custom_values, :versions,
25 :queries,
27 :queries,
26 :projects_trackers
28 :projects_trackers
27
29
28 def test_custom_fields_for_all_projects_should_be_available_in_global_queries
30 def test_custom_fields_for_all_projects_should_be_available_in_global_queries
29 query = Query.new(:project => nil, :name => '_')
31 query = Query.new(:project => nil, :name => '_')
30 assert query.available_filters.has_key?('cf_1')
32 assert query.available_filters.has_key?('cf_1')
31 assert !query.available_filters.has_key?('cf_3')
33 assert !query.available_filters.has_key?('cf_3')
32 end
34 end
33
35
34 def test_system_shared_versions_should_be_available_in_global_queries
36 def test_system_shared_versions_should_be_available_in_global_queries
35 Version.find(2).update_attribute :sharing, 'system'
37 Version.find(2).update_attribute :sharing, 'system'
36 query = Query.new(:project => nil, :name => '_')
38 query = Query.new(:project => nil, :name => '_')
37 assert query.available_filters.has_key?('fixed_version_id')
39 assert query.available_filters.has_key?('fixed_version_id')
38 assert query.available_filters['fixed_version_id'][:values].detect {|v| v.last == '2'}
40 assert query.available_filters['fixed_version_id'][:values].detect {|v| v.last == '2'}
39 end
41 end
40
42
41 def test_project_filter_in_global_queries
43 def test_project_filter_in_global_queries
42 query = Query.new(:project => nil, :name => '_')
44 query = Query.new(:project => nil, :name => '_')
43 project_filter = query.available_filters["project_id"]
45 project_filter = query.available_filters["project_id"]
44 assert_not_nil project_filter
46 assert_not_nil project_filter
45 project_ids = project_filter[:values].map{|p| p[1]}
47 project_ids = project_filter[:values].map{|p| p[1]}
46 assert project_ids.include?("1") #public project
48 assert project_ids.include?("1") #public project
47 assert !project_ids.include?("2") #private project user cannot see
49 assert !project_ids.include?("2") #private project user cannot see
48 end
50 end
49
51
50 def find_issues_with_query(query)
52 def find_issues_with_query(query)
51 Issue.find :all,
53 Issue.find :all,
52 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
54 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
53 :conditions => query.statement
55 :conditions => query.statement
54 end
56 end
55
57
56 def assert_find_issues_with_query_is_successful(query)
58 def assert_find_issues_with_query_is_successful(query)
57 assert_nothing_raised do
59 assert_nothing_raised do
58 find_issues_with_query(query)
60 find_issues_with_query(query)
59 end
61 end
60 end
62 end
61
63
62 def assert_query_statement_includes(query, condition)
64 def assert_query_statement_includes(query, condition)
63 assert query.statement.include?(condition), "Query statement condition not found in: #{query.statement}"
65 assert query.statement.include?(condition), "Query statement condition not found in: #{query.statement}"
64 end
66 end
65
67
66 def assert_query_result(expected, query)
68 def assert_query_result(expected, query)
67 assert_nothing_raised do
69 assert_nothing_raised do
68 assert_equal expected.map(&:id).sort, query.issues.map(&:id).sort
70 assert_equal expected.map(&:id).sort, query.issues.map(&:id).sort
69 assert_equal expected.size, query.issue_count
71 assert_equal expected.size, query.issue_count
70 end
72 end
71 end
73 end
72
74
73 def test_query_should_allow_shared_versions_for_a_project_query
75 def test_query_should_allow_shared_versions_for_a_project_query
74 subproject_version = Version.find(4)
76 subproject_version = Version.find(4)
75 query = Query.new(:project => Project.find(1), :name => '_')
77 query = Query.new(:project => Project.find(1), :name => '_')
76 query.add_filter('fixed_version_id', '=', [subproject_version.id.to_s])
78 query.add_filter('fixed_version_id', '=', [subproject_version.id.to_s])
77
79
78 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IN ('4')")
80 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IN ('4')")
79 end
81 end
80
82
81 def test_query_with_multiple_custom_fields
83 def test_query_with_multiple_custom_fields
82 query = Query.find(1)
84 query = Query.find(1)
83 assert query.valid?
85 assert query.valid?
84 assert query.statement.include?("#{CustomValue.table_name}.value IN ('MySQL')")
86 assert query.statement.include?("#{CustomValue.table_name}.value IN ('MySQL')")
85 issues = find_issues_with_query(query)
87 issues = find_issues_with_query(query)
86 assert_equal 1, issues.length
88 assert_equal 1, issues.length
87 assert_equal Issue.find(3), issues.first
89 assert_equal Issue.find(3), issues.first
88 end
90 end
89
91
90 def test_operator_none
92 def test_operator_none
91 query = Query.new(:project => Project.find(1), :name => '_')
93 query = Query.new(:project => Project.find(1), :name => '_')
92 query.add_filter('fixed_version_id', '!*', [''])
94 query.add_filter('fixed_version_id', '!*', [''])
93 query.add_filter('cf_1', '!*', [''])
95 query.add_filter('cf_1', '!*', [''])
94 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NULL")
96 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NULL")
95 assert query.statement.include?("#{CustomValue.table_name}.value IS NULL OR #{CustomValue.table_name}.value = ''")
97 assert query.statement.include?("#{CustomValue.table_name}.value IS NULL OR #{CustomValue.table_name}.value = ''")
96 find_issues_with_query(query)
98 find_issues_with_query(query)
97 end
99 end
98
100
99 def test_operator_none_for_integer
101 def test_operator_none_for_integer
100 query = Query.new(:project => Project.find(1), :name => '_')
102 query = Query.new(:project => Project.find(1), :name => '_')
101 query.add_filter('estimated_hours', '!*', [''])
103 query.add_filter('estimated_hours', '!*', [''])
102 issues = find_issues_with_query(query)
104 issues = find_issues_with_query(query)
103 assert !issues.empty?
105 assert !issues.empty?
104 assert issues.all? {|i| !i.estimated_hours}
106 assert issues.all? {|i| !i.estimated_hours}
105 end
107 end
106
108
107 def test_operator_none_for_date
109 def test_operator_none_for_date
108 query = Query.new(:project => Project.find(1), :name => '_')
110 query = Query.new(:project => Project.find(1), :name => '_')
109 query.add_filter('start_date', '!*', [''])
111 query.add_filter('start_date', '!*', [''])
110 issues = find_issues_with_query(query)
112 issues = find_issues_with_query(query)
111 assert !issues.empty?
113 assert !issues.empty?
112 assert issues.all? {|i| i.start_date.nil?}
114 assert issues.all? {|i| i.start_date.nil?}
113 end
115 end
114
116
115 def test_operator_none_for_string_custom_field
117 def test_operator_none_for_string_custom_field
116 query = Query.new(:project => Project.find(1), :name => '_')
118 query = Query.new(:project => Project.find(1), :name => '_')
117 query.add_filter('cf_2', '!*', [''])
119 query.add_filter('cf_2', '!*', [''])
118 assert query.has_filter?('cf_2')
120 assert query.has_filter?('cf_2')
119 issues = find_issues_with_query(query)
121 issues = find_issues_with_query(query)
120 assert !issues.empty?
122 assert !issues.empty?
121 assert issues.all? {|i| i.custom_field_value(2).blank?}
123 assert issues.all? {|i| i.custom_field_value(2).blank?}
122 end
124 end
123
125
124 def test_operator_all
126 def test_operator_all
125 query = Query.new(:project => Project.find(1), :name => '_')
127 query = Query.new(:project => Project.find(1), :name => '_')
126 query.add_filter('fixed_version_id', '*', [''])
128 query.add_filter('fixed_version_id', '*', [''])
127 query.add_filter('cf_1', '*', [''])
129 query.add_filter('cf_1', '*', [''])
128 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NOT NULL")
130 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NOT NULL")
129 assert query.statement.include?("#{CustomValue.table_name}.value IS NOT NULL AND #{CustomValue.table_name}.value <> ''")
131 assert query.statement.include?("#{CustomValue.table_name}.value IS NOT NULL AND #{CustomValue.table_name}.value <> ''")
130 find_issues_with_query(query)
132 find_issues_with_query(query)
131 end
133 end
132
134
133 def test_operator_all_for_date
135 def test_operator_all_for_date
134 query = Query.new(:project => Project.find(1), :name => '_')
136 query = Query.new(:project => Project.find(1), :name => '_')
135 query.add_filter('start_date', '*', [''])
137 query.add_filter('start_date', '*', [''])
136 issues = find_issues_with_query(query)
138 issues = find_issues_with_query(query)
137 assert !issues.empty?
139 assert !issues.empty?
138 assert issues.all? {|i| i.start_date.present?}
140 assert issues.all? {|i| i.start_date.present?}
139 end
141 end
140
142
141 def test_operator_all_for_string_custom_field
143 def test_operator_all_for_string_custom_field
142 query = Query.new(:project => Project.find(1), :name => '_')
144 query = Query.new(:project => Project.find(1), :name => '_')
143 query.add_filter('cf_2', '*', [''])
145 query.add_filter('cf_2', '*', [''])
144 assert query.has_filter?('cf_2')
146 assert query.has_filter?('cf_2')
145 issues = find_issues_with_query(query)
147 issues = find_issues_with_query(query)
146 assert !issues.empty?
148 assert !issues.empty?
147 assert issues.all? {|i| i.custom_field_value(2).present?}
149 assert issues.all? {|i| i.custom_field_value(2).present?}
148 end
150 end
149
151
150 def test_numeric_filter_should_not_accept_non_numeric_values
152 def test_numeric_filter_should_not_accept_non_numeric_values
151 query = Query.new(:name => '_')
153 query = Query.new(:name => '_')
152 query.add_filter('estimated_hours', '=', ['a'])
154 query.add_filter('estimated_hours', '=', ['a'])
153
155
154 assert query.has_filter?('estimated_hours')
156 assert query.has_filter?('estimated_hours')
155 assert !query.valid?
157 assert !query.valid?
156 end
158 end
157
159
158 def test_operator_is_on_float
160 def test_operator_is_on_float
159 Issue.update_all("estimated_hours = 171.2", "id=2")
161 Issue.update_all("estimated_hours = 171.2", "id=2")
160
162
161 query = Query.new(:name => '_')
163 query = Query.new(:name => '_')
162 query.add_filter('estimated_hours', '=', ['171.20'])
164 query.add_filter('estimated_hours', '=', ['171.20'])
163 issues = find_issues_with_query(query)
165 issues = find_issues_with_query(query)
164 assert_equal 1, issues.size
166 assert_equal 1, issues.size
165 assert_equal 2, issues.first.id
167 assert_equal 2, issues.first.id
166 end
168 end
167
169
168 def test_operator_is_on_integer_custom_field
170 def test_operator_is_on_integer_custom_field
169 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true)
171 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true)
170 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
172 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
171 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12')
173 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12')
172 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
174 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
173
175
174 query = Query.new(:name => '_')
176 query = Query.new(:name => '_')
175 query.add_filter("cf_#{f.id}", '=', ['12'])
177 query.add_filter("cf_#{f.id}", '=', ['12'])
176 issues = find_issues_with_query(query)
178 issues = find_issues_with_query(query)
177 assert_equal 1, issues.size
179 assert_equal 1, issues.size
178 assert_equal 2, issues.first.id
180 assert_equal 2, issues.first.id
179 end
181 end
180
182
181 def test_operator_is_on_integer_custom_field_should_accept_negative_value
183 def test_operator_is_on_integer_custom_field_should_accept_negative_value
182 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true)
184 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true)
183 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
185 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
184 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12')
186 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12')
185 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
187 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
186
188
187 query = Query.new(:name => '_')
189 query = Query.new(:name => '_')
188 query.add_filter("cf_#{f.id}", '=', ['-12'])
190 query.add_filter("cf_#{f.id}", '=', ['-12'])
189 assert query.valid?
191 assert query.valid?
190 issues = find_issues_with_query(query)
192 issues = find_issues_with_query(query)
191 assert_equal 1, issues.size
193 assert_equal 1, issues.size
192 assert_equal 2, issues.first.id
194 assert_equal 2, issues.first.id
193 end
195 end
194
196
195 def test_operator_is_on_float_custom_field
197 def test_operator_is_on_float_custom_field
196 f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true)
198 f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true)
197 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3')
199 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3')
198 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12.7')
200 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12.7')
199 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
201 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
200
202
201 query = Query.new(:name => '_')
203 query = Query.new(:name => '_')
202 query.add_filter("cf_#{f.id}", '=', ['12.7'])
204 query.add_filter("cf_#{f.id}", '=', ['12.7'])
203 issues = find_issues_with_query(query)
205 issues = find_issues_with_query(query)
204 assert_equal 1, issues.size
206 assert_equal 1, issues.size
205 assert_equal 2, issues.first.id
207 assert_equal 2, issues.first.id
206 end
208 end
207
209
208 def test_operator_is_on_float_custom_field_should_accept_negative_value
210 def test_operator_is_on_float_custom_field_should_accept_negative_value
209 f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true)
211 f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true)
210 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3')
212 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3')
211 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12.7')
213 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12.7')
212 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
214 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
213
215
214 query = Query.new(:name => '_')
216 query = Query.new(:name => '_')
215 query.add_filter("cf_#{f.id}", '=', ['-12.7'])
217 query.add_filter("cf_#{f.id}", '=', ['-12.7'])
216 assert query.valid?
218 assert query.valid?
217 issues = find_issues_with_query(query)
219 issues = find_issues_with_query(query)
218 assert_equal 1, issues.size
220 assert_equal 1, issues.size
219 assert_equal 2, issues.first.id
221 assert_equal 2, issues.first.id
220 end
222 end
221
223
222 def test_operator_is_on_multi_list_custom_field
224 def test_operator_is_on_multi_list_custom_field
223 f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
225 f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
224 :possible_values => ['value1', 'value2', 'value3'], :multiple => true)
226 :possible_values => ['value1', 'value2', 'value3'], :multiple => true)
225 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1')
227 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1')
226 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2')
228 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2')
227 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1')
229 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1')
228
230
229 query = Query.new(:name => '_')
231 query = Query.new(:name => '_')
230 query.add_filter("cf_#{f.id}", '=', ['value1'])
232 query.add_filter("cf_#{f.id}", '=', ['value1'])
231 issues = find_issues_with_query(query)
233 issues = find_issues_with_query(query)
232 assert_equal [1, 3], issues.map(&:id).sort
234 assert_equal [1, 3], issues.map(&:id).sort
233
235
234 query = Query.new(:name => '_')
236 query = Query.new(:name => '_')
235 query.add_filter("cf_#{f.id}", '=', ['value2'])
237 query.add_filter("cf_#{f.id}", '=', ['value2'])
236 issues = find_issues_with_query(query)
238 issues = find_issues_with_query(query)
237 assert_equal [1], issues.map(&:id).sort
239 assert_equal [1], issues.map(&:id).sort
238 end
240 end
239
241
240 def test_operator_is_not_on_multi_list_custom_field
242 def test_operator_is_not_on_multi_list_custom_field
241 f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
243 f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
242 :possible_values => ['value1', 'value2', 'value3'], :multiple => true)
244 :possible_values => ['value1', 'value2', 'value3'], :multiple => true)
243 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1')
245 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1')
244 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2')
246 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2')
245 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1')
247 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1')
246
248
247 query = Query.new(:name => '_')
249 query = Query.new(:name => '_')
248 query.add_filter("cf_#{f.id}", '!', ['value1'])
250 query.add_filter("cf_#{f.id}", '!', ['value1'])
249 issues = find_issues_with_query(query)
251 issues = find_issues_with_query(query)
250 assert !issues.map(&:id).include?(1)
252 assert !issues.map(&:id).include?(1)
251 assert !issues.map(&:id).include?(3)
253 assert !issues.map(&:id).include?(3)
252
254
253 query = Query.new(:name => '_')
255 query = Query.new(:name => '_')
254 query.add_filter("cf_#{f.id}", '!', ['value2'])
256 query.add_filter("cf_#{f.id}", '!', ['value2'])
255 issues = find_issues_with_query(query)
257 issues = find_issues_with_query(query)
256 assert !issues.map(&:id).include?(1)
258 assert !issues.map(&:id).include?(1)
257 assert issues.map(&:id).include?(3)
259 assert issues.map(&:id).include?(3)
258 end
260 end
259
261
260 def test_operator_greater_than
262 def test_operator_greater_than
261 query = Query.new(:project => Project.find(1), :name => '_')
263 query = Query.new(:project => Project.find(1), :name => '_')
262 query.add_filter('done_ratio', '>=', ['40'])
264 query.add_filter('done_ratio', '>=', ['40'])
263 assert query.statement.include?("#{Issue.table_name}.done_ratio >= 40.0")
265 assert query.statement.include?("#{Issue.table_name}.done_ratio >= 40.0")
264 find_issues_with_query(query)
266 find_issues_with_query(query)
265 end
267 end
266
268
267 def test_operator_greater_than_a_float
269 def test_operator_greater_than_a_float
268 query = Query.new(:project => Project.find(1), :name => '_')
270 query = Query.new(:project => Project.find(1), :name => '_')
269 query.add_filter('estimated_hours', '>=', ['40.5'])
271 query.add_filter('estimated_hours', '>=', ['40.5'])
270 assert query.statement.include?("#{Issue.table_name}.estimated_hours >= 40.5")
272 assert query.statement.include?("#{Issue.table_name}.estimated_hours >= 40.5")
271 find_issues_with_query(query)
273 find_issues_with_query(query)
272 end
274 end
273
275
274 def test_operator_greater_than_on_int_custom_field
276 def test_operator_greater_than_on_int_custom_field
275 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
277 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
276 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
278 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
277 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12')
279 CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12')
278 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
280 CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
279
281
280 query = Query.new(:project => Project.find(1), :name => '_')
282 query = Query.new(:project => Project.find(1), :name => '_')
281 query.add_filter("cf_#{f.id}", '>=', ['8'])
283 query.add_filter("cf_#{f.id}", '>=', ['8'])
282 issues = find_issues_with_query(query)
284 issues = find_issues_with_query(query)
283 assert_equal 1, issues.size
285 assert_equal 1, issues.size
284 assert_equal 2, issues.first.id
286 assert_equal 2, issues.first.id
285 end
287 end
286
288
287 def test_operator_lesser_than
289 def test_operator_lesser_than
288 query = Query.new(:project => Project.find(1), :name => '_')
290 query = Query.new(:project => Project.find(1), :name => '_')
289 query.add_filter('done_ratio', '<=', ['30'])
291 query.add_filter('done_ratio', '<=', ['30'])
290 assert query.statement.include?("#{Issue.table_name}.done_ratio <= 30.0")
292 assert query.statement.include?("#{Issue.table_name}.done_ratio <= 30.0")
291 find_issues_with_query(query)
293 find_issues_with_query(query)
292 end
294 end
293
295
294 def test_operator_lesser_than_on_custom_field
296 def test_operator_lesser_than_on_custom_field
295 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
297 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
296 query = Query.new(:project => Project.find(1), :name => '_')
298 query = Query.new(:project => Project.find(1), :name => '_')
297 query.add_filter("cf_#{f.id}", '<=', ['30'])
299 query.add_filter("cf_#{f.id}", '<=', ['30'])
298 assert query.statement.include?("CAST(custom_values.value AS decimal(60,3)) <= 30.0")
300 assert query.statement.include?("CAST(custom_values.value AS decimal(60,3)) <= 30.0")
299 find_issues_with_query(query)
301 find_issues_with_query(query)
300 end
302 end
301
303
302 def test_operator_between
304 def test_operator_between
303 query = Query.new(:project => Project.find(1), :name => '_')
305 query = Query.new(:project => Project.find(1), :name => '_')
304 query.add_filter('done_ratio', '><', ['30', '40'])
306 query.add_filter('done_ratio', '><', ['30', '40'])
305 assert_include "#{Issue.table_name}.done_ratio BETWEEN 30.0 AND 40.0", query.statement
307 assert_include "#{Issue.table_name}.done_ratio BETWEEN 30.0 AND 40.0", query.statement
306 find_issues_with_query(query)
308 find_issues_with_query(query)
307 end
309 end
308
310
309 def test_operator_between_on_custom_field
311 def test_operator_between_on_custom_field
310 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
312 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
311 query = Query.new(:project => Project.find(1), :name => '_')
313 query = Query.new(:project => Project.find(1), :name => '_')
312 query.add_filter("cf_#{f.id}", '><', ['30', '40'])
314 query.add_filter("cf_#{f.id}", '><', ['30', '40'])
313 assert_include "CAST(custom_values.value AS decimal(60,3)) BETWEEN 30.0 AND 40.0", query.statement
315 assert_include "CAST(custom_values.value AS decimal(60,3)) BETWEEN 30.0 AND 40.0", query.statement
314 find_issues_with_query(query)
316 find_issues_with_query(query)
315 end
317 end
316
318
317 def test_date_filter_should_not_accept_non_date_values
319 def test_date_filter_should_not_accept_non_date_values
318 query = Query.new(:name => '_')
320 query = Query.new(:name => '_')
319 query.add_filter('created_on', '=', ['a'])
321 query.add_filter('created_on', '=', ['a'])
320
322
321 assert query.has_filter?('created_on')
323 assert query.has_filter?('created_on')
322 assert !query.valid?
324 assert !query.valid?
323 end
325 end
324
326
325 def test_date_filter_should_not_accept_invalid_date_values
327 def test_date_filter_should_not_accept_invalid_date_values
326 query = Query.new(:name => '_')
328 query = Query.new(:name => '_')
327 query.add_filter('created_on', '=', ['2011-01-34'])
329 query.add_filter('created_on', '=', ['2011-01-34'])
328
330
329 assert query.has_filter?('created_on')
331 assert query.has_filter?('created_on')
330 assert !query.valid?
332 assert !query.valid?
331 end
333 end
332
334
333 def test_relative_date_filter_should_not_accept_non_integer_values
335 def test_relative_date_filter_should_not_accept_non_integer_values
334 query = Query.new(:name => '_')
336 query = Query.new(:name => '_')
335 query.add_filter('created_on', '>t-', ['a'])
337 query.add_filter('created_on', '>t-', ['a'])
336
338
337 assert query.has_filter?('created_on')
339 assert query.has_filter?('created_on')
338 assert !query.valid?
340 assert !query.valid?
339 end
341 end
340
342
341 def test_operator_date_equals
343 def test_operator_date_equals
342 query = Query.new(:name => '_')
344 query = Query.new(:name => '_')
343 query.add_filter('due_date', '=', ['2011-07-10'])
345 query.add_filter('due_date', '=', ['2011-07-10'])
344 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
346 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
345 find_issues_with_query(query)
347 find_issues_with_query(query)
346 end
348 end
347
349
348 def test_operator_date_lesser_than
350 def test_operator_date_lesser_than
349 query = Query.new(:name => '_')
351 query = Query.new(:name => '_')
350 query.add_filter('due_date', '<=', ['2011-07-10'])
352 query.add_filter('due_date', '<=', ['2011-07-10'])
351 assert_match /issues\.due_date <= '2011-07-10 23:59:59(\.9+)?/, query.statement
353 assert_match /issues\.due_date <= '2011-07-10 23:59:59(\.9+)?/, query.statement
352 find_issues_with_query(query)
354 find_issues_with_query(query)
353 end
355 end
354
356
355 def test_operator_date_greater_than
357 def test_operator_date_greater_than
356 query = Query.new(:name => '_')
358 query = Query.new(:name => '_')
357 query.add_filter('due_date', '>=', ['2011-07-10'])
359 query.add_filter('due_date', '>=', ['2011-07-10'])
358 assert_match /issues\.due_date > '2011-07-09 23:59:59(\.9+)?'/, query.statement
360 assert_match /issues\.due_date > '2011-07-09 23:59:59(\.9+)?'/, query.statement
359 find_issues_with_query(query)
361 find_issues_with_query(query)
360 end
362 end
361
363
362 def test_operator_date_between
364 def test_operator_date_between
363 query = Query.new(:name => '_')
365 query = Query.new(:name => '_')
364 query.add_filter('due_date', '><', ['2011-06-23', '2011-07-10'])
366 query.add_filter('due_date', '><', ['2011-06-23', '2011-07-10'])
365 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
367 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
366 find_issues_with_query(query)
368 find_issues_with_query(query)
367 end
369 end
368
370
369 def test_operator_in_more_than
371 def test_operator_in_more_than
370 Issue.find(7).update_attribute(:due_date, (Date.today + 15))
372 Issue.find(7).update_attribute(:due_date, (Date.today + 15))
371 query = Query.new(:project => Project.find(1), :name => '_')
373 query = Query.new(:project => Project.find(1), :name => '_')
372 query.add_filter('due_date', '>t+', ['15'])
374 query.add_filter('due_date', '>t+', ['15'])
373 issues = find_issues_with_query(query)
375 issues = find_issues_with_query(query)
374 assert !issues.empty?
376 assert !issues.empty?
375 issues.each {|issue| assert(issue.due_date >= (Date.today + 15))}
377 issues.each {|issue| assert(issue.due_date >= (Date.today + 15))}
376 end
378 end
377
379
378 def test_operator_in_less_than
380 def test_operator_in_less_than
379 query = Query.new(:project => Project.find(1), :name => '_')
381 query = Query.new(:project => Project.find(1), :name => '_')
380 query.add_filter('due_date', '<t+', ['15'])
382 query.add_filter('due_date', '<t+', ['15'])
381 issues = find_issues_with_query(query)
383 issues = find_issues_with_query(query)
382 assert !issues.empty?
384 assert !issues.empty?
383 issues.each {|issue| assert(issue.due_date >= Date.today && issue.due_date <= (Date.today + 15))}
385 issues.each {|issue| assert(issue.due_date >= Date.today && issue.due_date <= (Date.today + 15))}
384 end
386 end
385
387
386 def test_operator_less_than_ago
388 def test_operator_less_than_ago
387 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
389 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
388 query = Query.new(:project => Project.find(1), :name => '_')
390 query = Query.new(:project => Project.find(1), :name => '_')
389 query.add_filter('due_date', '>t-', ['3'])
391 query.add_filter('due_date', '>t-', ['3'])
390 issues = find_issues_with_query(query)
392 issues = find_issues_with_query(query)
391 assert !issues.empty?
393 assert !issues.empty?
392 issues.each {|issue| assert(issue.due_date >= (Date.today - 3) && issue.due_date <= Date.today)}
394 issues.each {|issue| assert(issue.due_date >= (Date.today - 3) && issue.due_date <= Date.today)}
393 end
395 end
394
396
395 def test_operator_more_than_ago
397 def test_operator_more_than_ago
396 Issue.find(7).update_attribute(:due_date, (Date.today - 10))
398 Issue.find(7).update_attribute(:due_date, (Date.today - 10))
397 query = Query.new(:project => Project.find(1), :name => '_')
399 query = Query.new(:project => Project.find(1), :name => '_')
398 query.add_filter('due_date', '<t-', ['10'])
400 query.add_filter('due_date', '<t-', ['10'])
399 assert query.statement.include?("#{Issue.table_name}.due_date <=")
401 assert query.statement.include?("#{Issue.table_name}.due_date <=")
400 issues = find_issues_with_query(query)
402 issues = find_issues_with_query(query)
401 assert !issues.empty?
403 assert !issues.empty?
402 issues.each {|issue| assert(issue.due_date <= (Date.today - 10))}
404 issues.each {|issue| assert(issue.due_date <= (Date.today - 10))}
403 end
405 end
404
406
405 def test_operator_in
407 def test_operator_in
406 Issue.find(7).update_attribute(:due_date, (Date.today + 2))
408 Issue.find(7).update_attribute(:due_date, (Date.today + 2))
407 query = Query.new(:project => Project.find(1), :name => '_')
409 query = Query.new(:project => Project.find(1), :name => '_')
408 query.add_filter('due_date', 't+', ['2'])
410 query.add_filter('due_date', 't+', ['2'])
409 issues = find_issues_with_query(query)
411 issues = find_issues_with_query(query)
410 assert !issues.empty?
412 assert !issues.empty?
411 issues.each {|issue| assert_equal((Date.today + 2), issue.due_date)}
413 issues.each {|issue| assert_equal((Date.today + 2), issue.due_date)}
412 end
414 end
413
415
414 def test_operator_ago
416 def test_operator_ago
415 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
417 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
416 query = Query.new(:project => Project.find(1), :name => '_')
418 query = Query.new(:project => Project.find(1), :name => '_')
417 query.add_filter('due_date', 't-', ['3'])
419 query.add_filter('due_date', 't-', ['3'])
418 issues = find_issues_with_query(query)
420 issues = find_issues_with_query(query)
419 assert !issues.empty?
421 assert !issues.empty?
420 issues.each {|issue| assert_equal((Date.today - 3), issue.due_date)}
422 issues.each {|issue| assert_equal((Date.today - 3), issue.due_date)}
421 end
423 end
422
424
423 def test_operator_today
425 def test_operator_today
424 query = Query.new(:project => Project.find(1), :name => '_')
426 query = Query.new(:project => Project.find(1), :name => '_')
425 query.add_filter('due_date', 't', [''])
427 query.add_filter('due_date', 't', [''])
426 issues = find_issues_with_query(query)
428 issues = find_issues_with_query(query)
427 assert !issues.empty?
429 assert !issues.empty?
428 issues.each {|issue| assert_equal Date.today, issue.due_date}
430 issues.each {|issue| assert_equal Date.today, issue.due_date}
429 end
431 end
430
432
431 def test_operator_this_week_on_date
433 def test_operator_this_week_on_date
432 query = Query.new(:project => Project.find(1), :name => '_')
434 query = Query.new(:project => Project.find(1), :name => '_')
433 query.add_filter('due_date', 'w', [''])
435 query.add_filter('due_date', 'w', [''])
434 find_issues_with_query(query)
436 find_issues_with_query(query)
435 end
437 end
436
438
437 def test_operator_this_week_on_datetime
439 def test_operator_this_week_on_datetime
438 query = Query.new(:project => Project.find(1), :name => '_')
440 query = Query.new(:project => Project.find(1), :name => '_')
439 query.add_filter('created_on', 'w', [''])
441 query.add_filter('created_on', 'w', [''])
440 find_issues_with_query(query)
442 find_issues_with_query(query)
441 end
443 end
442
444
443 def test_operator_contains
445 def test_operator_contains
444 query = Query.new(:project => Project.find(1), :name => '_')
446 query = Query.new(:project => Project.find(1), :name => '_')
445 query.add_filter('subject', '~', ['uNable'])
447 query.add_filter('subject', '~', ['uNable'])
446 assert query.statement.include?("LOWER(#{Issue.table_name}.subject) LIKE '%unable%'")
448 assert query.statement.include?("LOWER(#{Issue.table_name}.subject) LIKE '%unable%'")
447 result = find_issues_with_query(query)
449 result = find_issues_with_query(query)
448 assert result.empty?
450 assert result.empty?
449 result.each {|issue| assert issue.subject.downcase.include?('unable') }
451 result.each {|issue| assert issue.subject.downcase.include?('unable') }
450 end
452 end
451
453
452 def test_range_for_this_week_with_week_starting_on_monday
454 def test_range_for_this_week_with_week_starting_on_monday
453 I18n.locale = :fr
455 I18n.locale = :fr
454 assert_equal '1', I18n.t(:general_first_day_of_week)
456 assert_equal '1', I18n.t(:general_first_day_of_week)
455
457
456 Date.stubs(:today).returns(Date.parse('2011-04-29'))
458 Date.stubs(:today).returns(Date.parse('2011-04-29'))
457
459
458 query = Query.new(:project => Project.find(1), :name => '_')
460 query = Query.new(:project => Project.find(1), :name => '_')
459 query.add_filter('due_date', 'w', [''])
461 query.add_filter('due_date', 'w', [''])
460 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}"
462 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}"
461 I18n.locale = :en
463 I18n.locale = :en
462 end
464 end
463
465
464 def test_range_for_this_week_with_week_starting_on_sunday
466 def test_range_for_this_week_with_week_starting_on_sunday
465 I18n.locale = :en
467 I18n.locale = :en
466 assert_equal '7', I18n.t(:general_first_day_of_week)
468 assert_equal '7', I18n.t(:general_first_day_of_week)
467
469
468 Date.stubs(:today).returns(Date.parse('2011-04-29'))
470 Date.stubs(:today).returns(Date.parse('2011-04-29'))
469
471
470 query = Query.new(:project => Project.find(1), :name => '_')
472 query = Query.new(:project => Project.find(1), :name => '_')
471 query.add_filter('due_date', 'w', [''])
473 query.add_filter('due_date', 'w', [''])
472 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}"
474 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}"
473 end
475 end
474
476
475 def test_operator_does_not_contains
477 def test_operator_does_not_contains
476 query = Query.new(:project => Project.find(1), :name => '_')
478 query = Query.new(:project => Project.find(1), :name => '_')
477 query.add_filter('subject', '!~', ['uNable'])
479 query.add_filter('subject', '!~', ['uNable'])
478 assert query.statement.include?("LOWER(#{Issue.table_name}.subject) NOT LIKE '%unable%'")
480 assert query.statement.include?("LOWER(#{Issue.table_name}.subject) NOT LIKE '%unable%'")
479 find_issues_with_query(query)
481 find_issues_with_query(query)
480 end
482 end
481
483
482 def test_filter_assigned_to_me
484 def test_filter_assigned_to_me
483 user = User.find(2)
485 user = User.find(2)
484 group = Group.find(10)
486 group = Group.find(10)
485 User.current = user
487 User.current = user
486 i1 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => user)
488 i1 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => user)
487 i2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => group)
489 i2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => group)
488 i3 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => Group.find(11))
490 i3 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => Group.find(11))
489 group.users << user
491 group.users << user
490
492
491 query = Query.new(:name => '_', :filters => { 'assigned_to_id' => {:operator => '=', :values => ['me']}})
493 query = Query.new(:name => '_', :filters => { 'assigned_to_id' => {:operator => '=', :values => ['me']}})
492 result = query.issues
494 result = query.issues
493 assert_equal Issue.visible.all(:conditions => {:assigned_to_id => ([2] + user.reload.group_ids)}).sort_by(&:id), result.sort_by(&:id)
495 assert_equal Issue.visible.all(:conditions => {:assigned_to_id => ([2] + user.reload.group_ids)}).sort_by(&:id), result.sort_by(&:id)
494
496
495 assert result.include?(i1)
497 assert result.include?(i1)
496 assert result.include?(i2)
498 assert result.include?(i2)
497 assert !result.include?(i3)
499 assert !result.include?(i3)
498 end
500 end
499
501
500 def test_user_custom_field_filtered_on_me
502 def test_user_custom_field_filtered_on_me
501 User.current = User.find(2)
503 User.current = User.find(2)
502 cf = IssueCustomField.create!(:field_format => 'user', :is_for_all => true, :is_filter => true, :name => 'User custom field', :tracker_ids => [1])
504 cf = IssueCustomField.create!(:field_format => 'user', :is_for_all => true, :is_filter => true, :name => 'User custom field', :tracker_ids => [1])
503 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '2'}, :subject => 'Test', :author_id => 1)
505 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '2'}, :subject => 'Test', :author_id => 1)
504 issue2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '3'})
506 issue2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '3'})
505
507
506 query = Query.new(:name => '_', :project => Project.find(1))
508 query = Query.new(:name => '_', :project => Project.find(1))
507 filter = query.available_filters["cf_#{cf.id}"]
509 filter = query.available_filters["cf_#{cf.id}"]
508 assert_not_nil filter
510 assert_not_nil filter
509 assert_include 'me', filter[:values].map{|v| v[1]}
511 assert_include 'me', filter[:values].map{|v| v[1]}
510
512
511 query.filters = { "cf_#{cf.id}" => {:operator => '=', :values => ['me']}}
513 query.filters = { "cf_#{cf.id}" => {:operator => '=', :values => ['me']}}
512 result = query.issues
514 result = query.issues
513 assert_equal 1, result.size
515 assert_equal 1, result.size
514 assert_equal issue1, result.first
516 assert_equal issue1, result.first
515 end
517 end
516
518
517 def test_filter_my_projects
519 def test_filter_my_projects
518 User.current = User.find(2)
520 User.current = User.find(2)
519 query = Query.new(:name => '_')
521 query = Query.new(:name => '_')
520 filter = query.available_filters['project_id']
522 filter = query.available_filters['project_id']
521 assert_not_nil filter
523 assert_not_nil filter
522 assert_include 'mine', filter[:values].map{|v| v[1]}
524 assert_include 'mine', filter[:values].map{|v| v[1]}
523
525
524 query.filters = { 'project_id' => {:operator => '=', :values => ['mine']}}
526 query.filters = { 'project_id' => {:operator => '=', :values => ['mine']}}
525 result = query.issues
527 result = query.issues
526 assert_nil result.detect {|issue| !User.current.member_of?(issue.project)}
528 assert_nil result.detect {|issue| !User.current.member_of?(issue.project)}
527 end
529 end
528
530
529 def test_filter_watched_issues
531 def test_filter_watched_issues
530 User.current = User.find(1)
532 User.current = User.find(1)
531 query = Query.new(:name => '_', :filters => { 'watcher_id' => {:operator => '=', :values => ['me']}})
533 query = Query.new(:name => '_', :filters => { 'watcher_id' => {:operator => '=', :values => ['me']}})
532 result = find_issues_with_query(query)
534 result = find_issues_with_query(query)
533 assert_not_nil result
535 assert_not_nil result
534 assert !result.empty?
536 assert !result.empty?
535 assert_equal Issue.visible.watched_by(User.current).sort_by(&:id), result.sort_by(&:id)
537 assert_equal Issue.visible.watched_by(User.current).sort_by(&:id), result.sort_by(&:id)
536 User.current = nil
538 User.current = nil
537 end
539 end
538
540
539 def test_filter_unwatched_issues
541 def test_filter_unwatched_issues
540 User.current = User.find(1)
542 User.current = User.find(1)
541 query = Query.new(:name => '_', :filters => { 'watcher_id' => {:operator => '!', :values => ['me']}})
543 query = Query.new(:name => '_', :filters => { 'watcher_id' => {:operator => '!', :values => ['me']}})
542 result = find_issues_with_query(query)
544 result = find_issues_with_query(query)
543 assert_not_nil result
545 assert_not_nil result
544 assert !result.empty?
546 assert !result.empty?
545 assert_equal((Issue.visible - Issue.watched_by(User.current)).sort_by(&:id).size, result.sort_by(&:id).size)
547 assert_equal((Issue.visible - Issue.watched_by(User.current)).sort_by(&:id).size, result.sort_by(&:id).size)
546 User.current = nil
548 User.current = nil
547 end
549 end
548
550
549 def test_statement_should_be_nil_with_no_filters
551 def test_statement_should_be_nil_with_no_filters
550 q = Query.new(:name => '_')
552 q = Query.new(:name => '_')
551 q.filters = {}
553 q.filters = {}
552
554
553 assert q.valid?
555 assert q.valid?
554 assert_nil q.statement
556 assert_nil q.statement
555 end
557 end
556
558
557 def test_default_columns
559 def test_default_columns
558 q = Query.new
560 q = Query.new
559 assert !q.columns.empty?
561 assert !q.columns.empty?
560 end
562 end
561
563
562 def test_set_column_names
564 def test_set_column_names
563 q = Query.new
565 q = Query.new
564 q.column_names = ['tracker', :subject, '', 'unknonw_column']
566 q.column_names = ['tracker', :subject, '', 'unknonw_column']
565 assert_equal [:tracker, :subject], q.columns.collect {|c| c.name}
567 assert_equal [:tracker, :subject], q.columns.collect {|c| c.name}
566 c = q.columns.first
568 c = q.columns.first
567 assert q.has_column?(c)
569 assert q.has_column?(c)
568 end
570 end
569
571
570 def test_query_should_preload_spent_hours
572 def test_query_should_preload_spent_hours
571 q = Query.new(:name => '_', :column_names => [:subject, :spent_hours])
573 q = Query.new(:name => '_', :column_names => [:subject, :spent_hours])
572 assert q.has_column?(:spent_hours)
574 assert q.has_column?(:spent_hours)
573 issues = q.issues
575 issues = q.issues
574 assert_not_nil issues.first.instance_variable_get("@spent_hours")
576 assert_not_nil issues.first.instance_variable_get("@spent_hours")
575 end
577 end
576
578
577 def test_groupable_columns_should_include_custom_fields
579 def test_groupable_columns_should_include_custom_fields
578 q = Query.new
580 q = Query.new
579 column = q.groupable_columns.detect {|c| c.name == :cf_1}
581 column = q.groupable_columns.detect {|c| c.name == :cf_1}
580 assert_not_nil column
582 assert_not_nil column
581 assert_kind_of QueryCustomFieldColumn, column
583 assert_kind_of QueryCustomFieldColumn, column
582 end
584 end
583
585
584 def test_groupable_columns_should_not_include_multi_custom_fields
586 def test_groupable_columns_should_not_include_multi_custom_fields
585 field = CustomField.find(1)
587 field = CustomField.find(1)
586 field.update_attribute :multiple, true
588 field.update_attribute :multiple, true
587
589
588 q = Query.new
590 q = Query.new
589 column = q.groupable_columns.detect {|c| c.name == :cf_1}
591 column = q.groupable_columns.detect {|c| c.name == :cf_1}
590 assert_nil column
592 assert_nil column
591 end
593 end
592
594
593 def test_grouped_with_valid_column
595 def test_grouped_with_valid_column
594 q = Query.new(:group_by => 'status')
596 q = Query.new(:group_by => 'status')
595 assert q.grouped?
597 assert q.grouped?
596 assert_not_nil q.group_by_column
598 assert_not_nil q.group_by_column
597 assert_equal :status, q.group_by_column.name
599 assert_equal :status, q.group_by_column.name
598 assert_not_nil q.group_by_statement
600 assert_not_nil q.group_by_statement
599 assert_equal 'status', q.group_by_statement
601 assert_equal 'status', q.group_by_statement
600 end
602 end
601
603
602 def test_grouped_with_invalid_column
604 def test_grouped_with_invalid_column
603 q = Query.new(:group_by => 'foo')
605 q = Query.new(:group_by => 'foo')
604 assert !q.grouped?
606 assert !q.grouped?
605 assert_nil q.group_by_column
607 assert_nil q.group_by_column
606 assert_nil q.group_by_statement
608 assert_nil q.group_by_statement
607 end
609 end
608
610
609 def test_sortable_columns_should_sort_assignees_according_to_user_format_setting
611 def test_sortable_columns_should_sort_assignees_according_to_user_format_setting
610 with_settings :user_format => 'lastname_coma_firstname' do
612 with_settings :user_format => 'lastname_coma_firstname' do
611 q = Query.new
613 q = Query.new
612 assert q.sortable_columns.has_key?('assigned_to')
614 assert q.sortable_columns.has_key?('assigned_to')
613 assert_equal %w(users.lastname users.firstname users.id), q.sortable_columns['assigned_to']
615 assert_equal %w(users.lastname users.firstname users.id), q.sortable_columns['assigned_to']
614 end
616 end
615 end
617 end
616
618
617 def test_sortable_columns_should_sort_authors_according_to_user_format_setting
619 def test_sortable_columns_should_sort_authors_according_to_user_format_setting
618 with_settings :user_format => 'lastname_coma_firstname' do
620 with_settings :user_format => 'lastname_coma_firstname' do
619 q = Query.new
621 q = Query.new
620 assert q.sortable_columns.has_key?('author')
622 assert q.sortable_columns.has_key?('author')
621 assert_equal %w(authors.lastname authors.firstname authors.id), q.sortable_columns['author']
623 assert_equal %w(authors.lastname authors.firstname authors.id), q.sortable_columns['author']
622 end
624 end
623 end
625 end
624
626
625 def test_sortable_columns_should_include_custom_field
627 def test_sortable_columns_should_include_custom_field
626 q = Query.new
628 q = Query.new
627 assert q.sortable_columns['cf_1']
629 assert q.sortable_columns['cf_1']
628 end
630 end
629
631
630 def test_sortable_columns_should_not_include_multi_custom_field
632 def test_sortable_columns_should_not_include_multi_custom_field
631 field = CustomField.find(1)
633 field = CustomField.find(1)
632 field.update_attribute :multiple, true
634 field.update_attribute :multiple, true
633
635
634 q = Query.new
636 q = Query.new
635 assert !q.sortable_columns['cf_1']
637 assert !q.sortable_columns['cf_1']
636 end
638 end
637
639
638 def test_default_sort
640 def test_default_sort
639 q = Query.new
641 q = Query.new
640 assert_equal [], q.sort_criteria
642 assert_equal [], q.sort_criteria
641 end
643 end
642
644
643 def test_set_sort_criteria_with_hash
645 def test_set_sort_criteria_with_hash
644 q = Query.new
646 q = Query.new
645 q.sort_criteria = {'0' => ['priority', 'desc'], '2' => ['tracker']}
647 q.sort_criteria = {'0' => ['priority', 'desc'], '2' => ['tracker']}
646 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
648 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
647 end
649 end
648
650
649 def test_set_sort_criteria_with_array
651 def test_set_sort_criteria_with_array
650 q = Query.new
652 q = Query.new
651 q.sort_criteria = [['priority', 'desc'], 'tracker']
653 q.sort_criteria = [['priority', 'desc'], 'tracker']
652 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
654 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
653 end
655 end
654
656
655 def test_create_query_with_sort
657 def test_create_query_with_sort
656 q = Query.new(:name => 'Sorted')
658 q = Query.new(:name => 'Sorted')
657 q.sort_criteria = [['priority', 'desc'], 'tracker']
659 q.sort_criteria = [['priority', 'desc'], 'tracker']
658 assert q.save
660 assert q.save
659 q.reload
661 q.reload
660 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
662 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
661 end
663 end
662
664
663 def test_sort_by_string_custom_field_asc
665 def test_sort_by_string_custom_field_asc
664 q = Query.new
666 q = Query.new
665 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
667 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
666 assert c
668 assert c
667 assert c.sortable
669 assert c.sortable
668 issues = Issue.find :all,
670 issues = Issue.find :all,
669 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
671 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
670 :conditions => q.statement,
672 :conditions => q.statement,
671 :order => "#{c.sortable} ASC"
673 :order => "#{c.sortable} ASC"
672 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
674 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
673 assert !values.empty?
675 assert !values.empty?
674 assert_equal values.sort, values
676 assert_equal values.sort, values
675 end
677 end
676
678
677 def test_sort_by_string_custom_field_desc
679 def test_sort_by_string_custom_field_desc
678 q = Query.new
680 q = Query.new
679 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
681 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
680 assert c
682 assert c
681 assert c.sortable
683 assert c.sortable
682 issues = Issue.find :all,
684 issues = Issue.find :all,
683 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
685 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
684 :conditions => q.statement,
686 :conditions => q.statement,
685 :order => "#{c.sortable} DESC"
687 :order => "#{c.sortable} DESC"
686 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
688 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
687 assert !values.empty?
689 assert !values.empty?
688 assert_equal values.sort.reverse, values
690 assert_equal values.sort.reverse, values
689 end
691 end
690
692
691 def test_sort_by_float_custom_field_asc
693 def test_sort_by_float_custom_field_asc
692 q = Query.new
694 q = Query.new
693 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'float' }
695 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'float' }
694 assert c
696 assert c
695 assert c.sortable
697 assert c.sortable
696 issues = Issue.find :all,
698 issues = Issue.find :all,
697 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
699 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
698 :conditions => q.statement,
700 :conditions => q.statement,
699 :order => "#{c.sortable} ASC"
701 :order => "#{c.sortable} ASC"
700 values = issues.collect {|i| begin; Kernel.Float(i.custom_value_for(c.custom_field).to_s); rescue; nil; end}.compact
702 values = issues.collect {|i| begin; Kernel.Float(i.custom_value_for(c.custom_field).to_s); rescue; nil; end}.compact
701 assert !values.empty?
703 assert !values.empty?
702 assert_equal values.sort, values
704 assert_equal values.sort, values
703 end
705 end
704
706
705 def test_invalid_query_should_raise_query_statement_invalid_error
707 def test_invalid_query_should_raise_query_statement_invalid_error
706 q = Query.new
708 q = Query.new
707 assert_raise Query::StatementInvalid do
709 assert_raise Query::StatementInvalid do
708 q.issues(:conditions => "foo = 1")
710 q.issues(:conditions => "foo = 1")
709 end
711 end
710 end
712 end
711
713
712 def test_issue_count
714 def test_issue_count
713 q = Query.new(:name => '_')
715 q = Query.new(:name => '_')
714 issue_count = q.issue_count
716 issue_count = q.issue_count
715 assert_equal q.issues.size, issue_count
717 assert_equal q.issues.size, issue_count
716 end
718 end
717
719
718 def test_issue_count_with_archived_issues
720 def test_issue_count_with_archived_issues
719 p = Project.generate!( :status => Project::STATUS_ARCHIVED )
721 p = Project.generate!( :status => Project::STATUS_ARCHIVED )
720 i = Issue.generate!( :project => p, :tracker => p.trackers.first )
722 i = Issue.generate!( :project => p, :tracker => p.trackers.first )
721 assert !i.visible?
723 assert !i.visible?
722
724
723 test_issue_count
725 test_issue_count
724 end
726 end
725
727
726 def test_issue_count_by_association_group
728 def test_issue_count_by_association_group
727 q = Query.new(:name => '_', :group_by => 'assigned_to')
729 q = Query.new(:name => '_', :group_by => 'assigned_to')
728 count_by_group = q.issue_count_by_group
730 count_by_group = q.issue_count_by_group
729 assert_kind_of Hash, count_by_group
731 assert_kind_of Hash, count_by_group
730 assert_equal %w(NilClass User), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
732 assert_equal %w(NilClass User), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
731 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
733 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
732 assert count_by_group.has_key?(User.find(3))
734 assert count_by_group.has_key?(User.find(3))
733 end
735 end
734
736
735 def test_issue_count_by_list_custom_field_group
737 def test_issue_count_by_list_custom_field_group
736 q = Query.new(:name => '_', :group_by => 'cf_1')
738 q = Query.new(:name => '_', :group_by => 'cf_1')
737 count_by_group = q.issue_count_by_group
739 count_by_group = q.issue_count_by_group
738 assert_kind_of Hash, count_by_group
740 assert_kind_of Hash, count_by_group
739 assert_equal %w(NilClass String), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
741 assert_equal %w(NilClass String), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
740 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
742 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
741 assert count_by_group.has_key?('MySQL')
743 assert count_by_group.has_key?('MySQL')
742 end
744 end
743
745
744 def test_issue_count_by_date_custom_field_group
746 def test_issue_count_by_date_custom_field_group
745 q = Query.new(:name => '_', :group_by => 'cf_8')
747 q = Query.new(:name => '_', :group_by => 'cf_8')
746 count_by_group = q.issue_count_by_group
748 count_by_group = q.issue_count_by_group
747 assert_kind_of Hash, count_by_group
749 assert_kind_of Hash, count_by_group
748 assert_equal %w(Date NilClass), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
750 assert_equal %w(Date NilClass), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
749 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
751 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
750 end
752 end
751
753
752 def test_issue_ids
754 def test_issue_ids
753 q = Query.new(:name => '_')
755 q = Query.new(:name => '_')
754 order = "issues.subject, issues.id"
756 order = "issues.subject, issues.id"
755 issues = q.issues(:order => order)
757 issues = q.issues(:order => order)
756 assert_equal issues.map(&:id), q.issue_ids(:order => order)
758 assert_equal issues.map(&:id), q.issue_ids(:order => order)
757 end
759 end
758
760
759 def test_label_for
761 def test_label_for
762 set_language_if_valid 'en'
760 q = Query.new
763 q = Query.new
761 assert_equal 'Assignee', q.label_for('assigned_to_id')
764 assert_equal 'Assignee', q.label_for('assigned_to_id')
762 end
765 end
763
766
764 def test_editable_by
767 def test_editable_by
765 admin = User.find(1)
768 admin = User.find(1)
766 manager = User.find(2)
769 manager = User.find(2)
767 developer = User.find(3)
770 developer = User.find(3)
768
771
769 # Public query on project 1
772 # Public query on project 1
770 q = Query.find(1)
773 q = Query.find(1)
771 assert q.editable_by?(admin)
774 assert q.editable_by?(admin)
772 assert q.editable_by?(manager)
775 assert q.editable_by?(manager)
773 assert !q.editable_by?(developer)
776 assert !q.editable_by?(developer)
774
777
775 # Private query on project 1
778 # Private query on project 1
776 q = Query.find(2)
779 q = Query.find(2)
777 assert q.editable_by?(admin)
780 assert q.editable_by?(admin)
778 assert !q.editable_by?(manager)
781 assert !q.editable_by?(manager)
779 assert q.editable_by?(developer)
782 assert q.editable_by?(developer)
780
783
781 # Private query for all projects
784 # Private query for all projects
782 q = Query.find(3)
785 q = Query.find(3)
783 assert q.editable_by?(admin)
786 assert q.editable_by?(admin)
784 assert !q.editable_by?(manager)
787 assert !q.editable_by?(manager)
785 assert q.editable_by?(developer)
788 assert q.editable_by?(developer)
786
789
787 # Public query for all projects
790 # Public query for all projects
788 q = Query.find(4)
791 q = Query.find(4)
789 assert q.editable_by?(admin)
792 assert q.editable_by?(admin)
790 assert !q.editable_by?(manager)
793 assert !q.editable_by?(manager)
791 assert !q.editable_by?(developer)
794 assert !q.editable_by?(developer)
792 end
795 end
793
796
794 def test_visible_scope
797 def test_visible_scope
795 query_ids = Query.visible(User.anonymous).map(&:id)
798 query_ids = Query.visible(User.anonymous).map(&:id)
796
799
797 assert query_ids.include?(1), 'public query on public project was not visible'
800 assert query_ids.include?(1), 'public query on public project was not visible'
798 assert query_ids.include?(4), 'public query for all projects was not visible'
801 assert query_ids.include?(4), 'public query for all projects was not visible'
799 assert !query_ids.include?(2), 'private query on public project was visible'
802 assert !query_ids.include?(2), 'private query on public project was visible'
800 assert !query_ids.include?(3), 'private query for all projects was visible'
803 assert !query_ids.include?(3), 'private query for all projects was visible'
801 assert !query_ids.include?(7), 'public query on private project was visible'
804 assert !query_ids.include?(7), 'public query on private project was visible'
802 end
805 end
803
806
804 context "#available_filters" do
807 context "#available_filters" do
805 setup do
808 setup do
806 @query = Query.new(:name => "_")
809 @query = Query.new(:name => "_")
807 end
810 end
808
811
809 should "include users of visible projects in cross-project view" do
812 should "include users of visible projects in cross-project view" do
810 users = @query.available_filters["assigned_to_id"]
813 users = @query.available_filters["assigned_to_id"]
811 assert_not_nil users
814 assert_not_nil users
812 assert users[:values].map{|u|u[1]}.include?("3")
815 assert users[:values].map{|u|u[1]}.include?("3")
813 end
816 end
814
817
815 should "include users of subprojects" do
818 should "include users of subprojects" do
816 user1 = User.generate_with_protected!
819 user1 = User.generate_with_protected!
817 user2 = User.generate_with_protected!
820 user2 = User.generate_with_protected!
818 project = Project.find(1)
821 project = Project.find(1)
819 Member.create!(:principal => user1, :project => project.children.visible.first, :role_ids => [1])
822 Member.create!(:principal => user1, :project => project.children.visible.first, :role_ids => [1])
820 @query.project = project
823 @query.project = project
821
824
822 users = @query.available_filters["assigned_to_id"]
825 users = @query.available_filters["assigned_to_id"]
823 assert_not_nil users
826 assert_not_nil users
824 assert users[:values].map{|u|u[1]}.include?(user1.id.to_s)
827 assert users[:values].map{|u|u[1]}.include?(user1.id.to_s)
825 assert !users[:values].map{|u|u[1]}.include?(user2.id.to_s)
828 assert !users[:values].map{|u|u[1]}.include?(user2.id.to_s)
826 end
829 end
827
830
828 should "include visible projects in cross-project view" do
831 should "include visible projects in cross-project view" do
829 projects = @query.available_filters["project_id"]
832 projects = @query.available_filters["project_id"]
830 assert_not_nil projects
833 assert_not_nil projects
831 assert projects[:values].map{|u|u[1]}.include?("1")
834 assert projects[:values].map{|u|u[1]}.include?("1")
832 end
835 end
833
836
834 context "'member_of_group' filter" do
837 context "'member_of_group' filter" do
835 should "be present" do
838 should "be present" do
836 assert @query.available_filters.keys.include?("member_of_group")
839 assert @query.available_filters.keys.include?("member_of_group")
837 end
840 end
838
841
839 should "be an optional list" do
842 should "be an optional list" do
840 assert_equal :list_optional, @query.available_filters["member_of_group"][:type]
843 assert_equal :list_optional, @query.available_filters["member_of_group"][:type]
841 end
844 end
842
845
843 should "have a list of the groups as values" do
846 should "have a list of the groups as values" do
844 Group.destroy_all # No fixtures
847 Group.destroy_all # No fixtures
845 group1 = Group.generate!.reload
848 group1 = Group.generate!.reload
846 group2 = Group.generate!.reload
849 group2 = Group.generate!.reload
847
850
848 expected_group_list = [
851 expected_group_list = [
849 [group1.name, group1.id.to_s],
852 [group1.name, group1.id.to_s],
850 [group2.name, group2.id.to_s]
853 [group2.name, group2.id.to_s]
851 ]
854 ]
852 assert_equal expected_group_list.sort, @query.available_filters["member_of_group"][:values].sort
855 assert_equal expected_group_list.sort, @query.available_filters["member_of_group"][:values].sort
853 end
856 end
854
857
855 end
858 end
856
859
857 context "'assigned_to_role' filter" do
860 context "'assigned_to_role' filter" do
858 should "be present" do
861 should "be present" do
859 assert @query.available_filters.keys.include?("assigned_to_role")
862 assert @query.available_filters.keys.include?("assigned_to_role")
860 end
863 end
861
864
862 should "be an optional list" do
865 should "be an optional list" do
863 assert_equal :list_optional, @query.available_filters["assigned_to_role"][:type]
866 assert_equal :list_optional, @query.available_filters["assigned_to_role"][:type]
864 end
867 end
865
868
866 should "have a list of the Roles as values" do
869 should "have a list of the Roles as values" do
867 assert @query.available_filters["assigned_to_role"][:values].include?(['Manager','1'])
870 assert @query.available_filters["assigned_to_role"][:values].include?(['Manager','1'])
868 assert @query.available_filters["assigned_to_role"][:values].include?(['Developer','2'])
871 assert @query.available_filters["assigned_to_role"][:values].include?(['Developer','2'])
869 assert @query.available_filters["assigned_to_role"][:values].include?(['Reporter','3'])
872 assert @query.available_filters["assigned_to_role"][:values].include?(['Reporter','3'])
870 end
873 end
871
874
872 should "not include the built in Roles as values" do
875 should "not include the built in Roles as values" do
873 assert ! @query.available_filters["assigned_to_role"][:values].include?(['Non member','4'])
876 assert ! @query.available_filters["assigned_to_role"][:values].include?(['Non member','4'])
874 assert ! @query.available_filters["assigned_to_role"][:values].include?(['Anonymous','5'])
877 assert ! @query.available_filters["assigned_to_role"][:values].include?(['Anonymous','5'])
875 end
878 end
876
879
877 end
880 end
878
881
879 end
882 end
880
883
881 context "#statement" do
884 context "#statement" do
882 context "with 'member_of_group' filter" do
885 context "with 'member_of_group' filter" do
883 setup do
886 setup do
884 Group.destroy_all # No fixtures
887 Group.destroy_all # No fixtures
885 @user_in_group = User.generate!
888 @user_in_group = User.generate!
886 @second_user_in_group = User.generate!
889 @second_user_in_group = User.generate!
887 @user_in_group2 = User.generate!
890 @user_in_group2 = User.generate!
888 @user_not_in_group = User.generate!
891 @user_not_in_group = User.generate!
889
892
890 @group = Group.generate!.reload
893 @group = Group.generate!.reload
891 @group.users << @user_in_group
894 @group.users << @user_in_group
892 @group.users << @second_user_in_group
895 @group.users << @second_user_in_group
893
896
894 @group2 = Group.generate!.reload
897 @group2 = Group.generate!.reload
895 @group2.users << @user_in_group2
898 @group2.users << @user_in_group2
896
899
897 end
900 end
898
901
899 should "search assigned to for users in the group" do
902 should "search assigned to for users in the group" do
900 @query = Query.new(:name => '_')
903 @query = Query.new(:name => '_')
901 @query.add_filter('member_of_group', '=', [@group.id.to_s])
904 @query.add_filter('member_of_group', '=', [@group.id.to_s])
902
905
903 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@user_in_group.id}','#{@second_user_in_group.id}')"
906 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@user_in_group.id}','#{@second_user_in_group.id}')"
904 assert_find_issues_with_query_is_successful @query
907 assert_find_issues_with_query_is_successful @query
905 end
908 end
906
909
907 should "search not assigned to any group member (none)" do
910 should "search not assigned to any group member (none)" do
908 @query = Query.new(:name => '_')
911 @query = Query.new(:name => '_')
909 @query.add_filter('member_of_group', '!*', [''])
912 @query.add_filter('member_of_group', '!*', [''])
910
913
911 # Users not in a group
914 # Users not in a group
912 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}')"
915 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}')"
913 assert_find_issues_with_query_is_successful @query
916 assert_find_issues_with_query_is_successful @query
914 end
917 end
915
918
916 should "search assigned to any group member (all)" do
919 should "search assigned to any group member (all)" do
917 @query = Query.new(:name => '_')
920 @query = Query.new(:name => '_')
918 @query.add_filter('member_of_group', '*', [''])
921 @query.add_filter('member_of_group', '*', [''])
919
922
920 # Only users in a group
923 # Only users in a group
921 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}')"
924 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}')"
922 assert_find_issues_with_query_is_successful @query
925 assert_find_issues_with_query_is_successful @query
923 end
926 end
924
927
925 should "return an empty set with = empty group" do
928 should "return an empty set with = empty group" do
926 @empty_group = Group.generate!
929 @empty_group = Group.generate!
927 @query = Query.new(:name => '_')
930 @query = Query.new(:name => '_')
928 @query.add_filter('member_of_group', '=', [@empty_group.id.to_s])
931 @query.add_filter('member_of_group', '=', [@empty_group.id.to_s])
929
932
930 assert_equal [], find_issues_with_query(@query)
933 assert_equal [], find_issues_with_query(@query)
931 end
934 end
932
935
933 should "return issues with ! empty group" do
936 should "return issues with ! empty group" do
934 @empty_group = Group.generate!
937 @empty_group = Group.generate!
935 @query = Query.new(:name => '_')
938 @query = Query.new(:name => '_')
936 @query.add_filter('member_of_group', '!', [@empty_group.id.to_s])
939 @query.add_filter('member_of_group', '!', [@empty_group.id.to_s])
937
940
938 assert_find_issues_with_query_is_successful @query
941 assert_find_issues_with_query_is_successful @query
939 end
942 end
940 end
943 end
941
944
942 context "with 'assigned_to_role' filter" do
945 context "with 'assigned_to_role' filter" do
943 setup do
946 setup do
944 @manager_role = Role.find_by_name('Manager')
947 @manager_role = Role.find_by_name('Manager')
945 @developer_role = Role.find_by_name('Developer')
948 @developer_role = Role.find_by_name('Developer')
946
949
947 @project = Project.generate!
950 @project = Project.generate!
948 @manager = User.generate!
951 @manager = User.generate!
949 @developer = User.generate!
952 @developer = User.generate!
950 @boss = User.generate!
953 @boss = User.generate!
951 @guest = User.generate!
954 @guest = User.generate!
952 User.add_to_project(@manager, @project, @manager_role)
955 User.add_to_project(@manager, @project, @manager_role)
953 User.add_to_project(@developer, @project, @developer_role)
956 User.add_to_project(@developer, @project, @developer_role)
954 User.add_to_project(@boss, @project, [@manager_role, @developer_role])
957 User.add_to_project(@boss, @project, [@manager_role, @developer_role])
955
958
956 @issue1 = Issue.generate_for_project!(@project, :assigned_to_id => @manager.id)
959 @issue1 = Issue.generate_for_project!(@project, :assigned_to_id => @manager.id)
957 @issue2 = Issue.generate_for_project!(@project, :assigned_to_id => @developer.id)
960 @issue2 = Issue.generate_for_project!(@project, :assigned_to_id => @developer.id)
958 @issue3 = Issue.generate_for_project!(@project, :assigned_to_id => @boss.id)
961 @issue3 = Issue.generate_for_project!(@project, :assigned_to_id => @boss.id)
959 @issue4 = Issue.generate_for_project!(@project, :assigned_to_id => @guest.id)
962 @issue4 = Issue.generate_for_project!(@project, :assigned_to_id => @guest.id)
960 @issue5 = Issue.generate_for_project!(@project)
963 @issue5 = Issue.generate_for_project!(@project)
961 end
964 end
962
965
963 should "search assigned to for users with the Role" do
966 should "search assigned to for users with the Role" do
964 @query = Query.new(:name => '_', :project => @project)
967 @query = Query.new(:name => '_', :project => @project)
965 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
968 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
966
969
967 assert_query_result [@issue1, @issue3], @query
970 assert_query_result [@issue1, @issue3], @query
968 end
971 end
969
972
970 should "search assigned to for users with the Role on the issue project" do
973 should "search assigned to for users with the Role on the issue project" do
971 other_project = Project.generate!
974 other_project = Project.generate!
972 User.add_to_project(@developer, other_project, @manager_role)
975 User.add_to_project(@developer, other_project, @manager_role)
973
976
974 @query = Query.new(:name => '_', :project => @project)
977 @query = Query.new(:name => '_', :project => @project)
975 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
978 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
976
979
977 assert_query_result [@issue1, @issue3], @query
980 assert_query_result [@issue1, @issue3], @query
978 end
981 end
979
982
980 should "return an empty set with empty role" do
983 should "return an empty set with empty role" do
981 @empty_role = Role.generate!
984 @empty_role = Role.generate!
982 @query = Query.new(:name => '_', :project => @project)
985 @query = Query.new(:name => '_', :project => @project)
983 @query.add_filter('assigned_to_role', '=', [@empty_role.id.to_s])
986 @query.add_filter('assigned_to_role', '=', [@empty_role.id.to_s])
984
987
985 assert_query_result [], @query
988 assert_query_result [], @query
986 end
989 end
987
990
988 should "search assigned to for users without the Role" do
991 should "search assigned to for users without the Role" do
989 @query = Query.new(:name => '_', :project => @project)
992 @query = Query.new(:name => '_', :project => @project)
990 @query.add_filter('assigned_to_role', '!', [@manager_role.id.to_s])
993 @query.add_filter('assigned_to_role', '!', [@manager_role.id.to_s])
991
994
992 assert_query_result [@issue2, @issue4, @issue5], @query
995 assert_query_result [@issue2, @issue4, @issue5], @query
993 end
996 end
994
997
995 should "search assigned to for users not assigned to any Role (none)" do
998 should "search assigned to for users not assigned to any Role (none)" do
996 @query = Query.new(:name => '_', :project => @project)
999 @query = Query.new(:name => '_', :project => @project)
997 @query.add_filter('assigned_to_role', '!*', [''])
1000 @query.add_filter('assigned_to_role', '!*', [''])
998
1001
999 assert_query_result [@issue4, @issue5], @query
1002 assert_query_result [@issue4, @issue5], @query
1000 end
1003 end
1001
1004
1002 should "search assigned to for users assigned to any Role (all)" do
1005 should "search assigned to for users assigned to any Role (all)" do
1003 @query = Query.new(:name => '_', :project => @project)
1006 @query = Query.new(:name => '_', :project => @project)
1004 @query.add_filter('assigned_to_role', '*', [''])
1007 @query.add_filter('assigned_to_role', '*', [''])
1005
1008
1006 assert_query_result [@issue1, @issue2, @issue3], @query
1009 assert_query_result [@issue1, @issue2, @issue3], @query
1007 end
1010 end
1008
1011
1009 should "return issues with ! empty role" do
1012 should "return issues with ! empty role" do
1010 @empty_role = Role.generate!
1013 @empty_role = Role.generate!
1011 @query = Query.new(:name => '_', :project => @project)
1014 @query = Query.new(:name => '_', :project => @project)
1012 @query.add_filter('assigned_to_role', '!', [@empty_role.id.to_s])
1015 @query.add_filter('assigned_to_role', '!', [@empty_role.id.to_s])
1013
1016
1014 assert_query_result [@issue1, @issue2, @issue3, @issue4, @issue5], @query
1017 assert_query_result [@issue1, @issue2, @issue3, @issue4, @issue5], @query
1015 end
1018 end
1016 end
1019 end
1017 end
1020 end
1018
1021
1019 end
1022 end
General Comments 0
You need to be logged in to leave comments. Login now