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 |
|