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