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