Patch #19622 » journal_filters.diff
app/helpers/queries_helper.rb | ||
---|---|---|
26 | 26 |
query.available_filters.map do |field, field_options| |
27 | 27 |
if field_options[:type] == :relation |
28 | 28 |
group = :label_related_issues |
29 |
elsif field =~ /_id_was\z/ |
|
30 |
group = :label_history |
|
29 | 31 |
elsif field =~ /^(.+)\./ |
30 | 32 |
# association filters |
31 | 33 |
group = "field_#{$1}" |
app/models/issue_query.rb | ||
---|---|---|
168 | 168 | |
169 | 169 |
add_available_filter "tracker_id", |
170 | 170 |
:type => :list, :values => trackers.collect{|s| [s.name, s.id.to_s] } |
171 | ||
171 | 172 |
add_available_filter "priority_id", |
172 | 173 |
:type => :list, :values => IssuePriority.all.collect{|s| [s.name, s.id.to_s] } |
173 | 174 | |
... | ... | |
208 | 209 |
:values => categories.collect{|s| [s.name, s.id.to_s] } |
209 | 210 |
end |
210 | 211 | |
212 |
add_available_filter "status_id_was", |
|
213 |
:type => :list, :values => IssueStatus.sorted.collect{|s| [s.name, s.id.to_s] } |
|
214 |
add_available_filter "priority_id_was", |
|
215 |
:type => :list, :values => IssuePriority.all.collect{|s| [s.name, s.id.to_s] } |
|
216 |
add_available_filter "tracker_id_was", |
|
217 |
:type => :list, :values => trackers.collect{|s| [s.name, s.id.to_s] } |
|
218 |
add_available_filter "assigned_to_id_was", |
|
219 |
:type => :list, :values => assigned_to_values unless assigned_to_values.empty? |
|
220 | ||
211 | 221 |
add_available_filter "subject", :type => :text |
212 | 222 |
add_available_filter "created_on", :type => :date_past |
213 | 223 |
add_available_filter "updated_on", :type => :date_past |
... | ... | |
289 | 299 |
end |
290 | 300 |
end |
291 | 301 | |
302 |
def history_filters |
|
303 |
filters.select { |k,_| k =~ /_was\z/ } |
|
304 |
end |
|
305 | ||
306 |
def history_join_clause |
|
307 |
return nil if history_filters.blank? |
|
308 |
history_filters.keys.map do |f| |
|
309 |
"INNER JOIN journals AS j_#{f} ON j_#{f}.journalized_id = issues.id AND j_#{f}.journalized_type = 'Issue'" + |
|
310 |
"INNER JOIN journal_details AS jd_#{f} ON jd_#{f}.journal_id = j_#{f}.id" |
|
311 |
end.join(' ') |
|
312 |
end |
|
313 | ||
292 | 314 |
# Returns the issue count |
293 | 315 |
def issue_count |
294 |
Issue.visible.joins(:status, :project).where(statement).count |
|
316 |
Issue.visible. |
|
317 |
joins(:status, :project). |
|
318 |
joins(history_join_clause). |
|
319 |
where(statement). |
|
320 |
count |
|
295 | 321 |
rescue ::ActiveRecord::StatementInvalid => e |
296 | 322 |
raise StatementInvalid.new(e.message) |
297 | 323 |
end |
... | ... | |
304 | 330 |
# Rails3 will raise an (unexpected) RecordNotFound if there's only a nil group value |
305 | 331 |
r = Issue.visible. |
306 | 332 |
joins(:status, :project). |
333 |
joins(history_join_clause). |
|
307 | 334 |
where(statement). |
308 | 335 |
joins(joins_for_order_statement(group_by_statement)). |
309 | 336 |
group(group_by_statement). |
... | ... | |
328 | 355 | |
329 | 356 |
scope = Issue.visible. |
330 | 357 |
joins(:status, :project). |
358 |
joins(history_join_clause). |
|
331 | 359 |
where(statement). |
332 | 360 |
includes(([:status, :project] + (options[:include] || [])).uniq). |
333 | 361 |
where(options[:conditions]). |
... | ... | |
360 | 388 | |
361 | 389 |
Issue.visible. |
362 | 390 |
joins(:status, :project). |
391 |
joins(history_join_clause). |
|
363 | 392 |
where(statement). |
364 | 393 |
includes(([:status, :project] + (options[:include] || [])).uniq). |
365 | 394 |
references(([:status, :project] + (options[:include] || [])).uniq). |
... | ... | |
401 | 430 |
raise StatementInvalid.new(e.message) |
402 | 431 |
end |
403 | 432 | |
433 |
# works for status_id_was & priority_id_was |
|
434 |
def sql_for_history_field(field, operator, values) |
|
435 |
field_name = field.sub('_was', '') |
|
436 |
select_values = values[0..-3] |
|
437 |
select_values = substitute_me_in_history_values(select_values) if field_name == 'assigned_to_id' |
|
438 |
date_from, date_to = values[-2..-1] |
|
439 |
journal_queries = [] |
|
440 |
journal_queries << "jd_#{field}.prop_key = '#{field_name}'" |
|
441 |
journal_queries << sql_for_field(field_name, operator, select_values, "jd_#{field}", "old_value") |
|
442 |
date_range_query = sql_for_history_date_range(field, date_from, date_to) |
|
443 |
journal_queries << date_range_query if date_range_query |
|
444 |
journal_queries.join(" AND ") |
|
445 |
end |
|
446 | ||
447 |
def substitute_me_in_history_values(values) |
|
448 |
idx = values.index {|v| v == 'me'} |
|
449 |
return values unless idx |
|
450 |
values[idx] = User.current.logged? ? User.current.id.to_s : '0' |
|
451 |
values |
|
452 |
end |
|
453 | ||
454 |
def sql_for_history_date_range(field, from, to) |
|
455 |
from, to = parse_date(from), parse_date(to) |
|
456 |
from || to ? date_clause("j_#{field}", 'created_on', from, to, false) : nil |
|
457 |
end |
|
458 | ||
404 | 459 |
def sql_for_watcher_id_field(field, operator, value) |
405 | 460 |
db_table = Watcher.table_name |
406 | 461 |
"#{Issue.table_name}.id #{ operator == '=' ? 'IN' : 'NOT IN' } (SELECT #{db_table}.watchable_id FROM #{db_table} WHERE #{db_table}.watchable_type='Issue' AND " + |
app/models/query.rb | ||
---|---|---|
584 | 584 |
if field =~ /cf_(\d+)$/ |
585 | 585 |
# custom field |
586 | 586 |
filters_clauses << sql_for_custom_field(field, operator, v, $1) |
587 |
elsif field =~ /_was\z/ && respond_to?("sql_for_history_field") |
|
588 |
filters_clauses << sql_for_history_field(field, operator, v) |
|
587 | 589 |
elsif respond_to?("sql_for_#{field}_field") |
588 | 590 |
# specific statement |
589 | 591 |
filters_clauses << send("sql_for_#{field}_field", field, operator, v) |
... | ... | |
712 | 714 |
end |
713 | 715 |
end |
714 | 716 |
when "o" |
715 |
sql = "#{queried_table_name}.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{self.class.connection.quoted_false})" if field == "status_id"
|
|
717 |
sql = "#{db_table}.#{db_field} IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{self.class.connection.quoted_false})" if field == "status_id"
|
|
716 | 718 |
when "c" |
717 |
sql = "#{queried_table_name}.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{self.class.connection.quoted_true})" if field == "status_id"
|
|
719 |
sql = "#{db_table}.#{db_field} IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{self.class.connection.quoted_true})" if field == "status_id"
|
|
718 | 720 |
when "><t-" |
719 | 721 |
# between today - n days and today |
720 | 722 |
sql = relative_date_clause(db_table, db_field, - value.first.to_i, 0, is_custom_filter) |
config/locales/en.yml | ||
---|---|---|
247 | 247 |
field_project: Project |
248 | 248 |
field_issue: Issue |
249 | 249 |
field_status: Status |
250 |
field_status_id_was: Previous status |
|
250 | 251 |
field_notes: Notes |
251 | 252 |
field_is_closed: Issue closed |
252 | 253 |
field_is_default: Default value |
253 | 254 |
field_tracker: Tracker |
255 |
field_tracker_id_was: Previous tracker |
|
254 | 256 |
field_subject: Subject |
255 | 257 |
field_due_date: Due date |
256 | 258 |
field_assigned_to: Assignee |
259 |
field_assigned_to_id_was: Previous assignee |
|
257 | 260 |
field_priority: Priority |
261 |
field_priority_id_was: Previous priority |
|
258 | 262 |
field_fixed_version: Target version |
259 | 263 |
field_user: User |
260 | 264 |
field_principal: Principal |
config/locales/pl.yml | ||
---|---|---|
224 | 224 |
field_admin: Administrator |
225 | 225 |
field_assignable: Zagadnienia mogą być przypisane do tej roli |
226 | 226 |
field_assigned_to: Przypisany do |
227 |
field_assigned_to_id_was: Poprzednio przypisany do |
|
227 | 228 |
field_attr_firstname: Imię atrybut |
228 | 229 |
field_attr_lastname: Nazwisko atrybut |
229 | 230 |
field_attr_login: Login atrybut |
... | ... | |
282 | 283 |
field_port: Port |
283 | 284 |
field_possible_values: Możliwe wartości |
284 | 285 |
field_priority: Priorytet |
286 |
field_priority_id_was: Poprzedni priorytet |
|
285 | 287 |
field_project: Projekt |
286 | 288 |
field_redirect_existing_links: Przekierowanie istniejących odnośników |
287 | 289 |
field_regexp: Wyrażenie regularne |
... | ... | |
291 | 293 |
field_start_date: Data rozpoczęcia |
292 | 294 |
field_start_page: Strona startowa |
293 | 295 |
field_status: Status |
296 |
field_status_id_was: Poprzedni status |
|
294 | 297 |
field_subject: Temat |
295 | 298 |
field_subproject: Podprojekt |
296 | 299 |
field_summary: Podsumowanie |
297 | 300 |
field_time_zone: Strefa czasowa |
298 | 301 |
field_title: Tytuł |
299 | 302 |
field_tracker: Typ zagadnienia |
303 |
field_tracker_id_was: Poprzedni typ zagadnienia |
|
300 | 304 |
field_type: Typ |
301 | 305 |
field_updated_on: Data modyfikacji |
302 | 306 |
field_url: URL |
public/javascripts/application.js | ||
---|---|---|
168 | 168 |
' <span class="toggle-multiselect"> </span></span>' |
169 | 169 |
); |
170 | 170 |
select = tr.find('td.values select'); |
171 |
if (values.length > 1) { select.attr('multiple', true); } |
|
171 |
if ( isHistoryFilter(field) ) { |
|
172 |
// history filters have 2 additional values in array |
|
173 |
// corresponding to `from` and `to` dates |
|
174 |
if (values.length > 3) { select.attr('multiple', true); } |
|
175 |
} else { |
|
176 |
if (values.length > 1) { select.attr('multiple', true); } |
|
177 |
} |
|
178 | ||
172 | 179 |
for (i = 0; i < filterValues.length; i++) { |
173 | 180 |
var filterValue = filterValues[i]; |
174 | 181 |
var option = $('<option>'); |
... | ... | |
225 | 232 |
$('#values_'+fieldId+'_2').val(values[1]); |
226 | 233 |
break; |
227 | 234 |
} |
235 | ||
236 |
if ( isHistoryFilter(fieldId) ) { |
|
237 |
tr.find('td.values').append( |
|
238 |
'<a href="#" id="enable_daterange_'+field+'" class="enable_daterange"><img src="/images/calendar.png" alt="select daterange" title="select daterange"></a>' + |
|
239 |
'<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_from" size="10" class="value date_value previous_date_range" /></span>' + |
|
240 |
'<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_to" size="10" class="value date_value previous_date_range" /></span>' + |
|
241 |
'<a style="display:none;" class="disable_daterange icon icon-cancel" title="disable daterange" href="#" />' |
|
242 |
); |
|
243 |
date_values = values.slice(Math.max(values.length - 2, 1)); |
|
244 |
$('#values_'+fieldId+'_from').val(date_values[0]).datepicker(datepickerOptions); |
|
245 |
$('#values_'+fieldId+'_to').val(date_values[1]).datepicker(datepickerOptions); |
|
246 |
} |
|
228 | 247 |
} |
229 | 248 | |
230 | 249 |
function toggleFilter(field) { |
... | ... | |
234 | 253 |
toggleOperator(field); |
235 | 254 |
} else { |
236 | 255 |
$("#operators_" + fieldId).hide().attr('disabled', true); |
256 |
if ( isHistoryFilter(field) ) { |
|
257 |
$('#values_'+fieldId+'_from').parent().hide(); |
|
258 |
$('#values_'+fieldId+'_to').parent().hide(); |
|
259 |
$('#values_'+fieldId+'_to').parent().siblings('a').hide(); |
|
260 |
} |
|
237 | 261 |
enableValues(field, []); |
238 | 262 |
} |
239 | 263 |
} |
... | ... | |
241 | 265 |
function enableValues(field, indexes) { |
242 | 266 |
var fieldId = field.replace('.', '_'); |
243 | 267 |
$('#tr_'+fieldId+' td.values .value').each(function(index) { |
268 |
if ( isHistoryFilter(this.id) ) return; |
|
244 | 269 |
if ($.inArray(index, indexes) >= 0) { |
245 | 270 |
$(this).removeAttr('disabled'); |
246 | 271 |
$(this).parents('span').first().show(); |
... | ... | |
298 | 323 |
enableValues(field, [0]); |
299 | 324 |
break; |
300 | 325 |
} |
326 |
showHistoryFiltersDateRange(); |
|
301 | 327 |
} |
302 | 328 | |
303 | 329 |
function toggleMultiSelect(el) { |
... | ... | |
313 | 339 |
} |
314 | 340 |
} |
315 | 341 | |
342 |
function isHistoryFilter(filter) { |
|
343 |
return filter.match(/_was$|_was_from$|_was_to$/); |
|
344 |
} |
|
345 | ||
346 |
function showHistoryFiltersDateRange() { |
|
347 |
$('a.enable_daterange').each(function(){ |
|
348 |
var date_inputs = $(this).siblings().find('.previous_date_range'); |
|
349 |
var date_values = date_inputs.map(function(){ |
|
350 |
return $(this).val(); |
|
351 |
}).get(); |
|
352 |
var matches = $.grep(date_values, function(val){ |
|
353 |
return val.match(/^\d{4}-\d{2}-\d{2}$/); |
|
354 |
}); |
|
355 |
if ( matches.length > 0 ) { |
|
356 |
$(this).hide(); |
|
357 |
date_inputs.closest('span').show(); |
|
358 |
$(this).siblings('a.disable_daterange').show(); |
|
359 |
} else { |
|
360 |
$(this).show(); |
|
361 |
$(this).siblings('a.disable_daterange').hide(); |
|
362 |
} |
|
363 |
}); |
|
364 |
} |
|
365 | ||
316 | 366 |
function showTab(name, url) { |
317 | 367 |
$('div#content .tab-content').hide(); |
318 | 368 |
$('div.tabs a').removeClass('selected'); |
... | ... | |
651 | 701 |
$(document).ready(defaultFocus); |
652 | 702 | |
653 | 703 |
$(function(){ |
704 |
$(document).on('click', 'a.enable_daterange', function(){ |
|
705 |
$(this).siblings().find('.previous_date_range').closest('span').show(); |
|
706 |
$(this).siblings('a.disable_daterange').show(); |
|
707 |
$(this).hide(); |
|
708 |
}); |
|
709 | ||
710 |
$(document).on('click', 'a.disable_daterange', function(){ |
|
711 |
$(this).siblings().find('.previous_date_range').val('').closest('span').hide(); |
|
712 |
$(this).siblings('a.enable_daterange').show(); |
|
713 |
$(this).hide(); |
|
714 |
}); |
|
715 |
}); |
|
716 | ||
717 |
$(function(){ |
|
654 | 718 |
if ($('#issue_tree .issues').length){ |
655 | 719 |
var fuzzyOptions = { |
656 | 720 |
searchClass: "fuzzy-search", |
public/stylesheets/application.css | ||
---|---|---|
1237 | 1237 |
z-index: 999 !important; |
1238 | 1238 |
} |
1239 | 1239 | |
1240 |
.previous_date_range { |
|
1241 |
margin-left:15px; |
|
1242 |
} |
|
1243 | ||
1244 |
a.enable_daterange { |
|
1245 |
margin-left:10px; |
|
1246 |
} |
|
1247 | ||
1248 |
a.enable_daterange img { |
|
1249 |
cursor: pointer; |
|
1250 |
vertical-align: middle; |
|
1251 |
margin-left: 4px; |
|
1252 |
} |
|
1253 | ||
1254 |
a.disable_daterange { |
|
1255 |
margin-left:5px; |
|
1256 |
} |
|
1257 | ||
1258 | ||
1240 | 1259 |
/* js fuzzy search */ |
1241 | 1260 | |
1242 | 1261 |
input.fuzzy-search{ |
... | ... | |
1279 | 1298 |
color: #ccc; |
1280 | 1299 |
} |
1281 | 1300 | |
1282 | ||
1283 | 1301 |
table.team_time_sheet tr td{ |
1284 | 1302 |
max-width: 200px; |
1285 | 1303 |
overflow: hidden; |
test/fixtures/issues.yml | ||
---|---|---|
1 |
---
|
|
2 |
issues_001:
|
|
1 |
--- |
|
2 |
issues_001: |
|
3 | 3 |
created_on: <%= 3.days.ago.to_s(:db) %> |
4 | 4 |
project_id: 1 |
5 | 5 |
updated_on: <%= 1.day.ago.to_s(:db) %> |
6 | 6 |
priority_id: 4 |
7 | 7 |
subject: Cannot print recipes |
8 | 8 |
id: 1 |
9 |
fixed_version_id:
|
|
9 |
fixed_version_id: |
|
10 | 10 |
category_id: 1 |
11 | 11 |
description: Unable to print recipes |
12 | 12 |
tracker_id: 1 |
13 |
assigned_to_id:
|
|
13 |
assigned_to_id: |
|
14 | 14 |
author_id: 2 |
15 | 15 |
status_id: 1 |
16 | 16 |
start_date: <%= 1.day.ago.to_date.to_s(:db) %> |
... | ... | |
19 | 19 |
lft: 1 |
20 | 20 |
rgt: 2 |
21 | 21 |
lock_version: 3 |
22 |
issues_002:
|
|
22 |
issues_002: |
|
23 | 23 |
created_on: 2006-07-19 21:04:21 +02:00 |
24 | 24 |
project_id: 1 |
25 | 25 |
updated_on: 2006-07-19 21:09:50 +02:00 |
... | ... | |
27 | 27 |
subject: Add ingredients categories |
28 | 28 |
id: 2 |
29 | 29 |
fixed_version_id: 2 |
30 |
category_id:
|
|
30 |
category_id: |
|
31 | 31 |
description: Ingredients of the recipe should be classified by categories |
32 | 32 |
tracker_id: 2 |
33 | 33 |
assigned_to_id: 3 |
34 | 34 |
author_id: 2 |
35 | 35 |
status_id: 2 |
36 | 36 |
start_date: <%= 2.day.ago.to_date.to_s(:db) %> |
37 |
due_date:
|
|
37 |
due_date: |
|
38 | 38 |
root_id: 2 |
39 | 39 |
lft: 1 |
40 | 40 |
rgt: 2 |
41 | 41 |
lock_version: 3 |
42 | 42 |
done_ratio: 30 |
43 |
issues_003:
|
|
43 |
issues_003: |
|
44 | 44 |
created_on: 2006-07-19 21:07:27 +02:00 |
45 | 45 |
project_id: 1 |
46 | 46 |
updated_on: 2006-07-19 21:07:27 +02:00 |
47 | 47 |
priority_id: 4 |
48 | 48 |
subject: Error 281 when updating a recipe |
49 | 49 |
id: 3 |
50 |
fixed_version_id:
|
|
51 |
category_id:
|
|
50 |
fixed_version_id: |
|
51 |
category_id: |
|
52 | 52 |
description: Error 281 is encountered when saving a recipe |
53 | 53 |
tracker_id: 1 |
54 | 54 |
assigned_to_id: 3 |
... | ... | |
59 | 59 |
root_id: 3 |
60 | 60 |
lft: 1 |
61 | 61 |
rgt: 2 |
62 |
issues_004:
|
|
62 |
issues_004: |
|
63 | 63 |
created_on: <%= 5.days.ago.to_s(:db) %> |
64 | 64 |
project_id: 2 |
65 | 65 |
updated_on: <%= 2.days.ago.to_s(:db) %> |
66 | 66 |
priority_id: 4 |
67 | 67 |
subject: Issue on project 2 |
68 | 68 |
id: 4 |
69 |
fixed_version_id:
|
|
70 |
category_id:
|
|
69 |
fixed_version_id: |
|
70 |
category_id: |
|
71 | 71 |
description: Issue on project 2 |
72 | 72 |
tracker_id: 1 |
73 | 73 |
assigned_to_id: 2 |
... | ... | |
76 | 76 |
root_id: 4 |
77 | 77 |
lft: 1 |
78 | 78 |
rgt: 2 |
79 |
issues_005:
|
|
79 |
issues_005: |
|
80 | 80 |
created_on: <%= 5.days.ago.to_s(:db) %> |
81 | 81 |
project_id: 3 |
82 | 82 |
updated_on: <%= 2.days.ago.to_s(:db) %> |
83 | 83 |
priority_id: 4 |
84 | 84 |
subject: Subproject issue |
85 | 85 |
id: 5 |
86 |
fixed_version_id:
|
|
87 |
category_id:
|
|
86 |
fixed_version_id: |
|
87 |
category_id: |
|
88 | 88 |
description: This is an issue on a cookbook subproject |
89 | 89 |
tracker_id: 1 |
90 |
assigned_to_id:
|
|
90 |
assigned_to_id: |
|
91 | 91 |
author_id: 2 |
92 | 92 |
status_id: 1 |
93 | 93 |
root_id: 5 |
94 | 94 |
lft: 1 |
95 | 95 |
rgt: 2 |
96 |
issues_006:
|
|
96 |
issues_006: |
|
97 | 97 |
created_on: <%= 1.minute.ago.to_s(:db) %> |
98 | 98 |
project_id: 5 |
99 | 99 |
updated_on: <%= 1.minute.ago.to_s(:db) %> |
100 | 100 |
priority_id: 4 |
101 | 101 |
subject: Issue of a private subproject |
102 | 102 |
id: 6 |
103 |
fixed_version_id:
|
|
104 |
category_id:
|
|
103 |
fixed_version_id: |
|
104 |
category_id: |
|
105 | 105 |
description: This is an issue of a private subproject of cookbook |
106 | 106 |
tracker_id: 1 |
107 |
assigned_to_id:
|
|
107 |
assigned_to_id: |
|
108 | 108 |
author_id: 2 |
109 | 109 |
status_id: 1 |
110 | 110 |
start_date: <%= Date.today.to_s(:db) %> |
... | ... | |
112 | 112 |
root_id: 6 |
113 | 113 |
lft: 1 |
114 | 114 |
rgt: 2 |
115 |
issues_007:
|
|
115 |
issues_007: |
|
116 | 116 |
created_on: <%= 10.days.ago.to_s(:db) %> |
117 | 117 |
project_id: 1 |
118 | 118 |
updated_on: <%= 10.days.ago.to_s(:db) %> |
119 | 119 |
priority_id: 5 |
120 | 120 |
subject: Issue due today |
121 | 121 |
id: 7 |
122 |
fixed_version_id:
|
|
123 |
category_id:
|
|
122 |
fixed_version_id: |
|
123 |
category_id: |
|
124 | 124 |
description: This is an issue that is due today |
125 | 125 |
tracker_id: 1 |
126 |
assigned_to_id:
|
|
126 |
assigned_to_id: |
|
127 | 127 |
author_id: 2 |
128 | 128 |
status_id: 1 |
129 | 129 |
start_date: <%= 10.days.ago.to_s(:db) %> |
... | ... | |
132 | 132 |
root_id: 7 |
133 | 133 |
lft: 1 |
134 | 134 |
rgt: 2 |
135 |
issues_008:
|
|
135 |
issues_008: |
|
136 | 136 |
created_on: <%= 10.days.ago.to_s(:db) %> |
137 | 137 |
project_id: 1 |
138 | 138 |
updated_on: <%= 10.days.ago.to_s(:db) %> |
139 | 139 |
priority_id: 5 |
140 | 140 |
subject: Closed issue |
141 | 141 |
id: 8 |
142 |
fixed_version_id:
|
|
143 |
category_id:
|
|
142 |
fixed_version_id: |
|
143 |
category_id: |
|
144 | 144 |
description: This is a closed issue. |
145 | 145 |
tracker_id: 1 |
146 |
assigned_to_id:
|
|
146 |
assigned_to_id: |
|
147 | 147 |
author_id: 2 |
148 | 148 |
status_id: 5 |
149 |
start_date:
|
|
150 |
due_date:
|
|
149 |
start_date: |
|
150 |
due_date: |
|
151 | 151 |
lock_version: 0 |
152 | 152 |
root_id: 8 |
153 | 153 |
lft: 1 |
154 | 154 |
rgt: 2 |
155 | 155 |
closed_on: <%= 3.days.ago.to_s(:db) %> |
156 |
issues_009:
|
|
156 |
issues_009: |
|
157 | 157 |
created_on: <%= 1.minute.ago.to_s(:db) %> |
158 | 158 |
project_id: 5 |
159 | 159 |
updated_on: <%= 1.minute.ago.to_s(:db) %> |
160 | 160 |
priority_id: 5 |
161 | 161 |
subject: Blocked Issue |
162 | 162 |
id: 9 |
163 |
fixed_version_id:
|
|
164 |
category_id:
|
|
163 |
fixed_version_id: |
|
164 |
category_id: |
|
165 | 165 |
description: This is an issue that is blocked by issue #10 |
166 | 166 |
tracker_id: 1 |
167 |
assigned_to_id:
|
|
167 |
assigned_to_id: |
|
168 | 168 |
author_id: 2 |
169 | 169 |
status_id: 1 |
170 | 170 |
start_date: <%= Date.today.to_s(:db) %> |
... | ... | |
172 | 172 |
root_id: 9 |
173 | 173 |
lft: 1 |
174 | 174 |
rgt: 2 |
175 |
issues_010:
|
|
175 |
issues_010: |
|
176 | 176 |
created_on: <%= 1.minute.ago.to_s(:db) %> |
177 | 177 |
project_id: 5 |
178 | 178 |
updated_on: <%= 1.minute.ago.to_s(:db) %> |
179 | 179 |
priority_id: 5 |
180 | 180 |
subject: Issue Doing the Blocking |
181 | 181 |
id: 10 |
182 |
fixed_version_id:
|
|
183 |
category_id:
|
|
182 |
fixed_version_id: |
|
183 |
category_id: |
|
184 | 184 |
description: This is an issue that blocks issue #9 |
185 | 185 |
tracker_id: 1 |
186 |
assigned_to_id:
|
|
186 |
assigned_to_id: |
|
187 | 187 |
author_id: 2 |
188 | 188 |
status_id: 1 |
189 | 189 |
start_date: <%= Date.today.to_s(:db) %> |
... | ... | |
191 | 191 |
root_id: 10 |
192 | 192 |
lft: 1 |
193 | 193 |
rgt: 2 |
194 |
issues_011:
|
|
194 |
issues_011: |
|
195 | 195 |
created_on: <%= 3.days.ago.to_s(:db) %> |
196 | 196 |
project_id: 1 |
197 | 197 |
updated_on: <%= 1.day.ago.to_s(:db) %> |
198 | 198 |
priority_id: 5 |
199 | 199 |
subject: Closed issue on a closed version |
200 | 200 |
id: 11 |
201 |
fixed_version_id: 1
|
|
201 |
fixed_version_id: 1 |
|
202 | 202 |
category_id: 1 |
203 | 203 |
description: |
204 | 204 |
tracker_id: 1 |
205 |
assigned_to_id:
|
|
205 |
assigned_to_id: |
|
206 | 206 |
author_id: 2 |
207 | 207 |
status_id: 5 |
208 | 208 |
start_date: <%= 1.day.ago.to_date.to_s(:db) %> |
... | ... | |
211 | 211 |
lft: 1 |
212 | 212 |
rgt: 2 |
213 | 213 |
closed_on: <%= 1.day.ago.to_s(:db) %> |
214 |
issues_012:
|
|
214 |
issues_012: |
|
215 | 215 |
created_on: <%= 3.days.ago.to_s(:db) %> |
216 | 216 |
project_id: 1 |
217 | 217 |
updated_on: <%= 1.day.ago.to_s(:db) %> |
218 | 218 |
priority_id: 5 |
219 | 219 |
subject: Closed issue on a locked version |
220 | 220 |
id: 12 |
221 |
fixed_version_id: 2
|
|
221 |
fixed_version_id: 2 |
|
222 | 222 |
category_id: 1 |
223 | 223 |
description: |
224 | 224 |
tracker_id: 1 |
225 |
assigned_to_id:
|
|
225 |
assigned_to_id: |
|
226 | 226 |
author_id: 3 |
227 | 227 |
status_id: 5 |
228 | 228 |
start_date: <%= 1.day.ago.to_date.to_s(:db) %> |
... | ... | |
238 | 238 |
priority_id: 4 |
239 | 239 |
subject: Subproject issue two |
240 | 240 |
id: 13 |
241 |
fixed_version_id:
|
|
242 |
category_id:
|
|
241 |
fixed_version_id: |
|
242 |
category_id: |
|
243 | 243 |
description: This is a second issue on a cookbook subproject |
244 | 244 |
tracker_id: 1 |
245 |
assigned_to_id:
|
|
245 |
assigned_to_id: |
|
246 | 246 |
author_id: 2 |
247 | 247 |
status_id: 1 |
248 | 248 |
root_id: 13 |
... | ... | |
255 | 255 |
updated_on: <%= 15.days.ago.to_s(:db) %> |
256 | 256 |
priority_id: 5 |
257 | 257 |
subject: Private issue on public project |
258 |
fixed_version_id: |
|
259 |
category_id: |
|
258 |
fixed_version_id: |
|
259 |
category_id: |
|
260 |
description: This is a private issue |
|
261 |
tracker_id: 1 |
|
262 |
assigned_to_id: |
|
263 |
author_id: 2 |
|
264 |
status_id: 1 |
|
265 |
is_private: true |
|
266 |
root_id: 14 |
|
267 |
lft: 1 |
|
268 |
rgt: 2 |
|
269 |
issues_015: |
|
270 |
id: 15 |
|
271 |
created_on: <%= 15.days.ago.to_s(:db) %> |
|
272 |
project_id: 1 |
|
273 |
updated_on: <%= 15.days.ago.to_s(:db) %> |
|
274 |
priority_id: 5 |
|
275 |
subject: Private issue on public project |
|
276 |
fixed_version_id: |
|
277 |
category_id: |
|
278 |
description: This is a private issue |
|
279 |
tracker_id: 1 |
|
280 |
assigned_to_id: |
|
281 |
author_id: 2 |
|
282 |
status_id: 1 |
|
283 |
is_private: true |
|
284 |
root_id: 14 |
|
285 |
lft: 1 |
|
286 |
rgt: 2 |
|
287 |
issues_016: |
|
288 |
id: 16 |
|
289 |
created_on: <%= 15.days.ago.to_s(:db) %> |
|
290 |
project_id: 1 |
|
291 |
updated_on: <%= 15.days.ago.to_s(:db) %> |
|
292 |
priority_id: 5 |
|
293 |
subject: Private issue on public project |
|
294 |
fixed_version_id: |
|
295 |
category_id: |
|
296 |
description: This is a private issue |
|
297 |
tracker_id: 1 |
|
298 |
assigned_to_id: |
|
299 |
author_id: 2 |
|
300 |
status_id: 1 |
|
301 |
is_private: true |
|
302 |
root_id: 14 |
|
303 |
lft: 1 |
|
304 |
rgt: 2 |
|
305 |
issues_015: |
|
306 |
id: 15 |
|
307 |
created_on: <%= 15.days.ago.to_s(:db) %> |
|
308 |
project_id: 1 |
|
309 |
updated_on: <%= 15.days.ago.to_s(:db) %> |
|
310 |
priority_id: 5 |
|
311 |
subject: Private issue on public project |
|
312 |
fixed_version_id: |
|
313 |
category_id: |
|
314 |
description: This is a private issue |
|
315 |
tracker_id: 1 |
|
316 |
assigned_to_id: |
|
317 |
author_id: 2 |
|
318 |
status_id: 1 |
|
319 |
is_private: true |
|
320 |
root_id: 14 |
|
321 |
lft: 1 |
|
322 |
rgt: 2 |
|
323 |
issues_016: |
|
324 |
id: 16 |
|
325 |
created_on: <%= 15.days.ago.to_s(:db) %> |
|
326 |
project_id: 1 |
|
327 |
updated_on: <%= 15.days.ago.to_s(:db) %> |
|
328 |
priority_id: 5 |
|
329 |
subject: Private issue on public project |
|
330 |
fixed_version_id: |
|
331 |
category_id: |
|
260 | 332 |
description: This is a private issue |
261 | 333 |
tracker_id: 1 |
262 |
assigned_to_id:
|
|
334 |
assigned_to_id: |
|
263 | 335 |
author_id: 2 |
264 | 336 |
status_id: 1 |
265 | 337 |
is_private: true |
test/fixtures/journal_details.yml | ||
---|---|---|
1 |
---
|
|
2 |
journal_details_001:
|
|
1 |
--- |
|
2 |
journal_details_001: |
|
3 | 3 |
old_value: "1" |
4 | 4 |
property: attr |
5 | 5 |
id: 1 |
6 | 6 |
value: "2" |
7 | 7 |
prop_key: status_id |
8 | 8 |
journal_id: 1 |
9 |
journal_details_002:
|
|
9 |
journal_details_002: |
|
10 | 10 |
old_value: "40" |
11 | 11 |
property: attr |
12 | 12 |
id: 2 |
... | ... | |
41 | 41 |
value: 060719210727_picture.jpg |
42 | 42 |
prop_key: 4 |
43 | 43 |
journal_id: 3 |
44 |
journal_details_007: |
|
45 |
old_value: '1' |
|
46 |
value: '4' |
|
47 |
property: attr |
|
48 |
id: 7 |
|
49 |
prop_key: status_id |
|
50 |
journal_id: 6 |
|
51 |
journal_details_008: |
|
52 |
old_value: '4' |
|
53 |
value: '3' |
|
54 |
property: attr |
|
55 |
id: 8 |
|
56 |
prop_key: status_id |
|
57 |
journal_id: 7 |
|
58 |
journal_details_009: |
|
59 |
old_value: '4' |
|
60 |
value: '1' |
|
61 |
property: attr |
|
62 |
id: 9 |
|
63 |
prop_key: priority_id |
|
64 |
journal_id: 8 |
|
65 |
journal_details_010: |
|
66 |
old_value: '4' |
|
67 |
value: '1' |
|
68 |
property: attr |
|
69 |
id: 10 |
|
70 |
prop_key: priority_id |
|
71 |
journal_id: 9 |
|
72 |
journal_details_011: |
|
73 |
old_value: '' |
|
74 |
value: '2' |
|
75 |
property: attr |
|
76 |
id: 11 |
|
77 |
prop_key: assigned_to_id |
|
78 |
journal_id: 10 |
|
79 |
journal_details_012: |
|
80 |
old_value: '2' |
|
81 |
value: '3' |
|
82 |
property: attr |
|
83 |
id: 12 |
|
84 |
prop_key: assigned_to_id |
|
85 |
journal_id: 11 |
|
86 |
journal_details_013: |
|
87 |
old_value: '1' |
|
88 |
value: '2' |
|
89 |
property: attr |
|
90 |
id: 13 |
|
91 |
prop_key: tracker_id |
|
92 |
journal_id: 12 |
test/fixtures/journals.yml | ||
---|---|---|
1 |
---
|
|
1 |
--- |
|
2 | 2 |
journals_001: |
3 | 3 |
created_on: <%= 2.days.ago.to_date.to_s(:db) %> |
4 | 4 |
notes: "Journal notes" |
... | ... | |
6 | 6 |
journalized_type: Issue |
7 | 7 |
user_id: 1 |
8 | 8 |
journalized_id: 1 |
9 |
journals_002:
|
|
9 |
journals_002: |
|
10 | 10 |
created_on: <%= 1.days.ago.to_date.to_s(:db) %> |
11 | 11 |
notes: "Some notes with Redmine links: #2, r2." |
12 | 12 |
id: 2 |
... | ... | |
34 | 34 |
user_id: 2 |
35 | 35 |
journalized_type: Issue |
36 | 36 |
journalized_id: 14 |
37 |
journals_006: |
|
38 |
id: 6 |
|
39 |
created_on: <%= 14.days.ago.to_date.to_s(:db) %> |
|
40 |
notes: "Change status" |
|
41 |
user_id: 2 |
|
42 |
journalized_type: Issue |
|
43 |
journalized_id: 15 |
|
44 |
journals_007: |
|
45 |
id: 7 |
|
46 |
created_on: <%= 13.days.ago.to_date.to_s(:db) %> |
|
47 |
notes: "Change status" |
|
48 |
user_id: 2 |
|
49 |
journalized_type: Issue |
|
50 |
journalized_id: 15 |
|
51 |
journals_008: |
|
52 |
id: 8 |
|
53 |
created_on: <%= 12.days.ago.to_date.to_s(:db) %> |
|
54 |
notes: "Change priority" |
|
55 |
user_id: 2 |
|
56 |
journalized_type: Issue |
|
57 |
journalized_id: 15 |
|
58 |
journals_009: |
|
59 |
id: 9 |
|
60 |
created_on: <%= 5.days.ago.to_date.to_s(:db) %> |
|
61 |
notes: "Change priority" |
|
62 |
user_id: 2 |
|
63 |
journalized_type: Issue |
|
64 |
journalized_id: 16 |
|
65 |
journals_010: |
|
66 |
id: 10 |
|
67 |
created_on: <%= 8.days.ago.to_date.to_s(:db) %> |
|
68 |
notes: "Change asignee" |
|
69 |
user_id: 2 |
|
70 |
journalized_type: Issue |
|
71 |
journalized_id: 16 |
|
72 |
journals_011: |
|
73 |
id: 11 |
|
74 |
created_on: <%= 6.days.ago.to_date.to_s(:db) %> |
|
75 |
notes: "Change asignee" |
|
76 |
user_id: 2 |
|
77 |
journalized_type: Issue |
|
78 |
journalized_id: 16 |
|
79 |
journals_012: |
|
80 |
id: 12 |
|
81 |
created_on: <%= 4.days.ago.to_date.to_s(:db) %> |
|
82 |
notes: "Change tracker" |
|
83 |
user_id: 2 |
|
84 |
journalized_type: Issue |
|
85 |
journalized_id: 16 |
test/unit/query_issue_history_test.rb | ||
---|---|---|
1 |
# Redmine - project management software |
|
2 |
# Copyright (C) 2006-2015 Jean-Philippe Lang |
|
3 |
# |
|
4 |
# This program is free software; you can redistribute it and/or |
|
5 |
# modify it under the terms of the GNU General Public License |
|
6 |
# as published by the Free Software Foundation; either version 2 |
|
7 |
# of the License, or (at your option) any later version. |
|
8 |
# |
|
9 |
# This program is distributed in the hope that it will be useful, |
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
# GNU General Public License for more details. |
|
13 |
# |
|
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 |
|
16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | ||
18 |
require File.expand_path('../../test_helper', __FILE__) |
|
19 | ||
20 |
class QueryTest < ActiveSupport::TestCase |
|
21 |
include Redmine::I18n |
|
22 | ||
23 |
fixtures :projects, :enabled_modules, :users, :members, |
|
24 |
:member_roles, :roles, :trackers, :issue_statuses, |
|
25 |
:issue_categories, :enumerations, :issues, |
|
26 |
:watchers, :custom_fields, :custom_values, :versions, |
|
27 |
:queries, |
|
28 |
:projects_trackers, |
|
29 |
:custom_fields_trackers, |
|
30 |
:workflows, |
|
31 |
:journals, |
|
32 |
:journal_details |
|
33 | ||
34 |
def setup |
|
35 |
User.current = nil |
|
36 |
end |
|
37 | ||
38 |
def test_available_filters_includes_status_id_was |
|
39 |
query = IssueQuery.new(:project => Project.find(1), :name => '_') |
|
40 |
assert query.available_filters.has_key? 'status_id_was' |
|
41 |
assert_equal :list, query.available_filters['status_id_was'][:type] |
|
42 |
assert_equal query.available_filters['status_id'][:values], query.available_filters['status_id_was'][:values] |
|
43 |
end |
|
44 | ||
45 |
def test_available_filters_includes_priority_id_was |
|
46 |
query = IssueQuery.new(:project => Project.find(1), :name => '_') |
|
47 |
assert query.available_filters.has_key? 'priority_id_was' |
|
48 |
assert_equal :list, query.available_filters['priority_id_was'][:type] |
|
49 |
assert_equal query.available_filters['priority_id'][:values], query.available_filters['priority_id_was'][:values] |
|
50 |
end |
|
51 | ||
52 |
def test_status_id_was_is_added_as_filter |
|
53 |
add_filter_to_query('status_id_was', '=', ['2', '', '']) |
|
54 |
assert @query.available_filters.has_key? @field |
|
55 |
assert @query.filters['status_id_was'] == { operator: @operator, values: @values } |
|
56 |
end |
|
57 | ||
58 |
def test_priority_id_was_is_added_as_filter |
|
59 |
add_filter_to_query('priority_id_was', '=', ['1', '', '']) |
|
60 |
assert @query.available_filters.has_key? @field |
|
61 |
assert @query.filters['priority_id_was'] == { operator: @operator, values: @values } |
|
62 |
end |
|
63 | ||
64 |
def test_status_id_was_with_dates_is_added_as_filter |
|
65 |
add_filter_to_query('status_id_was', '=', ['2', '2012-02-02', '2015-03-03']) |
|
66 |
assert @query.available_filters.has_key? @field |
|
67 |
assert @query.filters['status_id_was'] == { operator: @operator, values: @values } |
|
68 |
end |
|
69 | ||
70 |
def test_priority_id_was_with_dates_is_added_as_filter |
|
71 |
add_filter_to_query('priority_id_was', '=', ['2', '2012-02-02', '2015-03-03']) |
|
72 |
assert @query.available_filters.has_key? @field |
|
73 |
assert @query.filters['priority_id_was'] == { operator: @operator, values: @values } |
|
74 |
end |
|
75 | ||
76 |
def test_status_id_was_gets_proper_sql_query_with_no_dates |
|
77 |
add_filter_to_query('status_id_was', '=', ['2', '', '']) |
|
78 | ||
79 |
generated_query = @query.sql_for_history_field(@field, @operator, @values) |
|
80 |
expected_query = "jd_status_id_was.prop_key = 'status_id' AND jd_status_id_was.old_value IN ('2')" |
|
81 |
assert_equal expected_query, generated_query |
|
82 |
assert_match expected_query, @query.statement, 'query not included in statement' |
|
83 |
end |
|
84 | ||
85 |
def test_priority_id_was_gets_proper_sql_query_with_no_dates |
|
86 |
add_filter_to_query('priority_id_was', '=', ['2', '', '']) |
|
87 | ||
88 |
generated_query = @query.sql_for_history_field(@field, @operator, @values) |
|
89 |
expected_query = "jd_priority_id_was.prop_key = 'priority_id' AND jd_priority_id_was.old_value IN ('2')" |
|
90 |
assert_equal expected_query, generated_query |
|
91 |
assert_match expected_query, @query.statement, 'query not included in statement' |
|
92 |
end |
|
93 | ||
94 |
def test_status_id_was_gets_proper_sql_query_with_both_dates |
|
95 |
add_filter_to_query('status_id_was', '=', ['2', '2012-02-02', '2015-03-03']) |
|
96 |
generated_query = @query.sql_for_history_field(@field, @operator, @values) |
|
97 |
expected_query = "jd_status_id_was.prop_key = 'status_id' AND jd_status_id_was.old_value IN ('2') AND j_status_id_was.created_on > '2012-02-01 23:59:59.999999' AND j_status_id_was.created_on <= '2015-03-03 23:59:59.999999'" |
|
98 |
assert_equal expected_query, generated_query |
|
99 |
assert_match expected_query, @query.statement, 'query not included in statement' |
|
100 |
end |
|
101 | ||
102 |
def test_status_id_was_gets_proper_sql_query_with_both_dates |
|
103 |
add_filter_to_query('priority_id_was', '=', ['2', '2012-02-02', '2015-03-03']) |
|
104 |
generated_query = @query.sql_for_history_field(@field, @operator, @values) |
|
105 |
expected_query = "jd_priority_id_was.prop_key = 'priority_id' AND jd_priority_id_was.old_value IN ('2') AND j_priority_id_was.created_on > '2012-02-01 23:59:59.999999' AND j_priority_id_was.created_on <= '2015-03-03 23:59:59.999999'" |
|
106 |
assert_equal expected_query, generated_query |
|
107 |
assert_match expected_query, @query.statement, 'query not included in statement' |
|
108 |
end |
|
109 | ||
110 |
def test_status_id_was_gets_proper_sql_query_with_from_date |
|
111 |
add_filter_to_query('status_id_was', '=', ['2', '2012-02-02', '']) |
|
112 |
generated_query = @query.sql_for_history_field(@field, @operator, @values) |
|
113 |
expected_query = "jd_status_id_was.prop_key = 'status_id' AND jd_status_id_was.old_value IN ('2') AND j_status_id_was.created_on > '2012-02-01 23:59:59.999999'" |
|
114 |
assert_equal expected_query, generated_query |
|
115 |
assert_match expected_query, @query.statement, 'query not included in statement' |
|
116 |
end |
|
117 | ||
118 |
def test_priority_id_was_gets_proper_sql_query_with_from_date |
|
119 |
add_filter_to_query('priority_id_was', '=', ['2', '2012-02-02', '']) |
|
120 |
generated_query = @query.sql_for_history_field(@field, @operator, @values) |
|
121 |
expected_query = "jd_priority_id_was.prop_key = 'priority_id' AND jd_priority_id_was.old_value IN ('2') AND j_priority_id_was.created_on > '2012-02-01 23:59:59.999999'" |
|
122 |
assert_equal expected_query, generated_query |
|
123 |
assert_match expected_query, @query.statement, 'query not included in statement' |
|
124 |
end |
|
125 | ||
126 |
def test_status_id_was_gets_proper_sql_query_with_to_date |
|
127 |
add_filter_to_query('status_id_was', '=', ['2', '', '2012-02-02']) |
|
128 |
generated_query = @query.sql_for_history_field(@field, @operator, @values) |
|
129 |
expected_query = "jd_status_id_was.prop_key = 'status_id' AND jd_status_id_was.old_value IN ('2') AND j_status_id_was.created_on <= '2012-02-02 23:59:59.999999'" |
|
130 |
assert_equal expected_query, generated_query |
|
131 |
assert_match expected_query, @query.statement, 'query not included in statement' |
|
132 |
end |
|
133 | ||
134 |
def test_status_id_was_gets_proper_sql_query_with_to_date |
|
135 |
add_filter_to_query('priority_id_was', '=', ['2', '', '2012-02-02']) |
|
136 |
generated_query = @query.sql_for_history_field(@field, @operator, @values) |
|
137 |
expected_query = "jd_priority_id_was.prop_key = 'priority_id' AND jd_priority_id_was.old_value IN ('2') AND j_priority_id_was.created_on <= '2012-02-02 23:59:59.999999'" |
|
138 |
assert_equal expected_query, generated_query |
|
139 |
assert_match expected_query, @query.statement, 'query not included in statement' |
|
140 |
end |
|
141 | ||
142 |
def test_status_id_issues_return_proper_issue_without_date |
|
143 |
add_filter_to_query('status_id_was', '=', ['4', '', '']) |
|
144 |
assert_include Issue.find(15), @query.issues |
|
145 |
assert_equal 1, @query.issues.count |
|
146 |
end |
|
147 | ||
148 |
def test_status_id_issues_return_proper_issue_with_date |
|
149 |
add_filter_to_query('status_id_was', '=', ['4', (Date.today-15.days).to_s, (Date.today-10.days).to_s]) |
|
150 |
assert_include Issue.find(15), @query.issues |
|
151 |
assert_equal 1, @query.issues.count |
|
152 |
end |
|
153 | ||
154 |
def test_status_id_shouldnt_return_any_issue_for_a_specific_range |
|
155 |
add_filter_to_query('status_id_was', '=', ['4', (Date.today-8.days).to_s, (Date.today-7.days).to_s]) |
|
156 |
assert_not_include Issue.find(15), @query.issues |
|
157 |
end |
|
158 | ||
159 |
def test_status_id_issues_return_proper_issues_without_date |
|
160 |
add_filter_to_query('priority_id_was', '=', ['4', '', '']) |
|
161 |
assert_include Issue.find(15), @query.issues |
|
162 |
assert_include Issue.find(16), @query.issues |
|
163 |
assert_equal 2, @query.issues.count |
|
164 |
end |
|
165 | ||
166 |
def test_status_id_issues_return_proper_issues_without_date |
|
167 |
add_filter_to_query('priority_id_was', '=', ['4', (Date.today-7.days).to_s, (Date.today-3.days).to_s]) |
|
168 |
assert_not_include Issue.find(15), @query.issues |
|
169 |
assert_include Issue.find(16), @query.issues |
|
170 |
end |
|
171 | ||
172 |
def test_assigned_to_id_issues_return_previous_asignee_with_dates |
|
173 |
add_filter_to_query('assigned_to_id_was', '=', ['2', (Date.today-10.days).to_s, (Date.today-3.days).to_s]) |
|
174 |
assert_include Issue.find(16), @query.issues |
|
175 |
assert_equal 1, @query.issues.count |
|
176 |
end |
|
177 | ||
178 |
def test_assigned_to_id_issues_return_previous_asignee_without_dates |
|
179 |
add_filter_to_query('assigned_to_id_was', '=', ['2', '', '']) |
|
180 |
assert_include Issue.find(16), @query.issues |
|
181 |
assert_equal 1, @query.issues.count |
|
182 |
end |
|
183 | ||
184 |
def test_assigned_to_id_issues_return_proper_issues_for_me_value |
|
185 |
User.current = User.find(2) |
|
186 |
add_filter_to_query('assigned_to_id_was', '=', ['me', (Date.today-10.days).to_s, (Date.today-3.days).to_s]) |
|
187 |
assert_include Issue.find(16), @query.issues |
|
188 |
assert_equal 1, @query.issues.count |
|
189 |
end |
|
190 | ||
191 |
def test_tracker_id_issues_return_proper_issue_with_dates |
|
192 |
add_filter_to_query('tracker_id_was', '=', ['1', (Date.today-10.days).to_s, (Date.today-3.days).to_s]) |
|
193 |
assert_include Issue.find(16), @query.issues |
|
194 |
assert_equal 1, @query.issues.count |
|
195 |
end |
|
196 | ||
197 |
def test_filters_return_issue_for_a_combined_history_query |
|
198 |
add_filter_to_query('priority_id_was', '=', ['4', (Date.today-7.days).to_s, (Date.today-3.days).to_s]) |
|
199 |
add_filter_to_query('tracker_id_was', '=', ['1', (Date.today-10.days).to_s, (Date.today-3.days).to_s]) |
|
200 |
add_filter_to_query('assigned_to_id_was', '=', ['2', (Date.today-10.days).to_s, (Date.today-3.days).to_s]) |
|
201 |
assert_include Issue.find(16), @query.issues |
|
202 |
assert_equal 1, @query.issues.count |
|
203 |
end |
|
204 | ||
205 |
private |
|
206 | ||
207 |
def add_filter_to_query(field, operator, values) |
|
208 |
@query ||= IssueQuery.new(:project => Project.find(1), :name => '_') |
|
209 |
@field, @operator, @values = field, operator, values |
|
210 |
@query.add_filter(field, operator, values) |
|
211 |
assert @query.valid? |
|
212 |
end |
|
213 |
end |