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