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