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