Feature #36320 » 20231117_36320.patch
| Gemfile | ||
|---|---|---|
| 2 | 2 | |
| 3 | 3 |
ruby '>= 2.7.0', '< 3.3.0' |
| 4 | 4 | |
| 5 |
gem 'rails', '6.1.7.6'
|
|
| 5 |
gem 'rails', '7.1.2'
|
|
| 6 | 6 |
gem 'rouge', '~> 4.2.0' |
| 7 | 7 |
gem 'request_store', '~> 1.5.0' |
| 8 | 8 |
gem 'mini_mime', '~> 1.1.0' |
| 9 |
gem "actionpack-xml_parser" |
|
| 9 |
gem "actionpack-xml_parser", '~> 2.0.1'
|
|
| 10 | 10 |
gem 'roadie-rails', '~> 3.1.0' |
| 11 | 11 |
gem 'marcel' |
| 12 | 12 |
gem 'mail', '~> 2.8.1' |
| ... | ... | |
| 87 | 87 |
warn("Please configure your config/database.yml first")
|
| 88 | 88 |
end |
| 89 | 89 | |
| 90 |
group :development, :test do |
|
| 91 |
gem 'debug' |
|
| 92 |
end |
|
| 93 | ||
| 90 | 94 |
group :development do |
| 91 | 95 |
gem 'listen', '~> 3.3' |
| 92 | 96 |
gem "yard" |
| app/controllers/application_controller.rb | ||
|---|---|---|
| 780 | 780 |
def _include_layout?(*args) |
| 781 | 781 |
api_request? ? false : super |
| 782 | 782 |
end |
| 783 | ||
| 784 |
# Note: Overrodes #_url_host_allowed? to avoid |
|
| 785 |
# URI::InvalidURIError: URI must be ascii only... |
|
| 786 |
# when determining if the redirect destination is its own host. |
|
| 787 |
# See: https://bugs.ruby-lang.org/issues/12852 |
|
| 788 |
def _url_host_allowed?(url) |
|
| 789 |
host = Addressable::URI.parse(url.to_s).host |
|
| 790 | ||
| 791 |
return true if host == request.host |
|
| 792 |
return false unless host.nil? |
|
| 793 |
return false unless url.to_s.start_with?("/")
|
|
| 794 |
!url.to_s.start_with?("//")
|
|
| 795 |
rescue TypeError |
|
| 796 |
false |
|
| 797 |
end |
|
| 798 | ||
| 799 |
def rendered_format |
|
| 800 |
return request.format if api_request? |
|
| 801 | ||
| 802 |
super |
|
| 803 |
end |
|
| 783 | 804 |
end |
| app/controllers/attachments_controller.rb | ||
|---|---|---|
| 100 | 100 |
def upload |
| 101 | 101 |
# Make sure that API users get used to set this content type |
| 102 | 102 |
# as it won't trigger Rails' automatic parsing of the request body for parameters |
| 103 |
unless request.content_type == 'application/octet-stream'
|
|
| 103 |
unless request.media_type == 'application/octet-stream'
|
|
| 104 | 104 |
head 406 |
| 105 | 105 |
return |
| 106 | 106 |
end |
| app/helpers/application_helper.rb | ||
|---|---|---|
| 259 | 259 |
when Array |
| 260 | 260 |
formatted_objects = object.map {|o| format_object(o, html)}
|
| 261 | 261 |
html ? safe_join(formatted_objects, ', ') : formatted_objects.join(', ')
|
| 262 |
when Time |
|
| 262 |
when Time, ActiveSupport::TimeWithZone
|
|
| 263 | 263 |
format_time(object) |
| 264 | 264 |
when Date |
| 265 | 265 |
format_date(object) |
| ... | ... | |
| 634 | 634 |
'span', nil, |
| 635 | 635 |
:class => "name icon icon-#{principal.class.name.downcase}"
|
| 636 | 636 |
) |
| 637 |
) + principal |
|
| 637 |
) + principal.to_s
|
|
| 638 | 638 |
) |
| 639 | 639 |
end |
| 640 | 640 |
s.html_safe |
| app/models/attachment.rb | ||
|---|---|---|
| 345 | 345 |
# }) |
| 346 | 346 |
# |
| 347 | 347 |
def self.update_attachments(attachments, params) |
| 348 |
params = params.transform_keys {|key| key.to_i}
|
|
| 349 | ||
| 348 |
converted = {}
|
|
| 349 |
params.each {|key, val| converted[key.to_i] = val}
|
|
| 350 | 350 |
saved = true |
| 351 | 351 |
transaction do |
| 352 | 352 |
attachments.each do |attachment| |
| 353 |
if p = params[attachment.id]
|
|
| 354 |
attachment.filename = p[:filename] if p.key?(:filename)
|
|
| 355 |
attachment.description = p[:description] if p.key?(:description)
|
|
| 353 |
if file = converted[attachment.id]
|
|
| 354 |
attachment.filename = file[:filename] if file.key?(:filename)
|
|
| 355 |
attachment.description = file[:description] if file.key?(:description)
|
|
| 356 | 356 |
saved &&= attachment.save |
| 357 | 357 |
end |
| 358 | 358 |
end |
| app/models/query.rb | ||
|---|---|---|
| 257 | 257 |
has_and_belongs_to_many :roles, :join_table => "#{table_name_prefix}queries_roles#{table_name_suffix}", :foreign_key => "query_id"
|
| 258 | 258 |
serialize :filters |
| 259 | 259 |
serialize :column_names |
| 260 |
serialize :sort_criteria, Array |
|
| 261 |
serialize :options, Hash |
|
| 260 |
serialize :sort_criteria, type: Array
|
|
| 261 |
serialize :options, type: Hash
|
|
| 262 | 262 | |
| 263 | 263 |
validates_presence_of :name |
| 264 | 264 |
validates_length_of :name, :maximum => 255 |
| ... | ... | |
| 1631 | 1631 |
else |
| 1632 | 1632 |
from = from - 1 # second |
| 1633 | 1633 |
end |
| 1634 |
if self.class.default_timezone == :utc
|
|
| 1634 |
if ActiveRecord.default_timezone == :utc
|
|
| 1635 | 1635 |
from = from.utc |
| 1636 | 1636 |
end |
| 1637 | 1637 |
s << ("#{table}.#{field} > '%s'" % [quoted_time(from, is_custom_filter)])
|
| ... | ... | |
| 1640 | 1640 |
if to.is_a?(Date) |
| 1641 | 1641 |
to = date_for_user_time_zone(to.year, to.month, to.day).end_of_day |
| 1642 | 1642 |
end |
| 1643 |
if self.class.default_timezone == :utc
|
|
| 1643 |
if ActiveRecord.default_timezone == :utc
|
|
| 1644 | 1644 |
to = to.utc |
| 1645 | 1645 |
end |
| 1646 | 1646 |
s << ("#{table}.#{field} <= '%s'" % [quoted_time(to, is_custom_filter)])
|
| app/models/role.rb | ||
|---|---|---|
| 76 | 76 |
has_many :members, :through => :member_roles |
| 77 | 77 |
acts_as_positioned :scope => :builtin |
| 78 | 78 | |
| 79 |
serialize :permissions, ::Role::PermissionsAttributeCoder |
|
| 79 |
serialize :permissions, coder: ::Role::PermissionsAttributeCoder
|
|
| 80 | 80 |
store :settings, :accessors => [:permissions_all_trackers, :permissions_tracker_ids] |
| 81 | 81 | |
| 82 | 82 |
validates_presence_of :name |
| app/views/custom_fields/_visibility_by_project_selector.html.erb | ||
|---|---|---|
| 4 | 4 |
<div id="custom_field_project_ids"> |
| 5 | 5 |
<% project_ids = @custom_field.project_ids.to_a %> |
| 6 | 6 |
<%= render_project_nested_lists(Project.all) do |p| |
| 7 |
content_tag('label', check_box_tag('custom_field[project_ids][]', p.id, project_ids.include?(p.id), :id => nil) + ' ' + p)
|
|
| 7 |
content_tag('label', check_box_tag('custom_field[project_ids][]', p.id, project_ids.include?(p.id), :id => nil) + ' ' + p.to_s)
|
|
| 8 | 8 |
end %> |
| 9 | 9 |
<%= hidden_field_tag('custom_field[project_ids][]', '', :id => nil) %>
|
| 10 | 10 |
</div> |
| config/application.rb | ||
|---|---|---|
| 23 | 23 |
# Application configuration should go into files in config/initializers |
| 24 | 24 |
# -- all .rb files in that directory are automatically loaded. |
| 25 | 25 | |
| 26 |
# Custom directories with classes and modules you want to be autoloadable.
|
|
| 27 |
config.autoloader = :zeitwerk
|
|
| 26 |
# Adds `lib` to `config.autoload_paths` and `config.eager_load_paths`.
|
|
| 27 |
config.autoload_lib(ignore: %w(tasks generators plugins))
|
|
| 28 | 28 | |
| 29 | 29 |
# Only load the plugins named here, in the order given (default is alphabetical). |
| 30 | 30 |
# :all can be used as a placeholder for all plugins not explicitly named. |
| 31 | 31 |
# config.plugins = [ :exception_notification, :ssl_requirement, :all ] |
| 32 | 32 | |
| 33 |
config.load_defaults 7.1 |
|
| 34 |
config.active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA1 |
|
| 35 |
config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA1 |
|
| 36 |
config.active_record.encryption.support_sha1_for_non_deterministic_encryption = true |
|
| 37 |
config.active_record.default_column_serializer = YAML |
|
| 38 |
config.active_record.belongs_to_required_by_default = false |
|
| 39 |
config.action_dispatch.cookies_serializer = :marshal |
|
| 40 |
config.action_controller.raise_on_missing_callback_actions = false |
|
| 41 |
config.active_support.remove_deprecated_time_with_zone_name = true |
|
| 42 |
config.active_support.cache_format_version = 7.1 |
|
| 43 | ||
| 33 | 44 |
config.active_record.store_full_sti_class = true |
| 34 | 45 |
config.active_record.default_timezone = :local |
| 35 | 46 |
config.active_record.yaml_column_permitted_classes = [ |
| config/environments/test.rb | ||
|---|---|---|
| 9 | 9 | |
| 10 | 10 |
Rails.application.configure do |
| 11 | 11 |
# Settings specified here will take precedence over those in config/application.rb. |
| 12 |
config.add_autoload_paths_to_load_path = true |
|
| 13 |
config.dom_testing_default_html_version = :html4 |
|
| 12 | 14 | |
| 13 | 15 |
config.cache_classes = true |
| 14 | 16 |
# config.action_view.cache_template_loading = true |
| ... | ... | |
| 30 | 32 |
config.cache_store = :null_store |
| 31 | 33 | |
| 32 | 34 |
# Raise exceptions instead of rendering exception templates. |
| 33 |
config.action_dispatch.show_exceptions = true
|
|
| 35 |
config.action_dispatch.show_exceptions = :all
|
|
| 34 | 36 | |
| 35 | 37 |
# Disable request forgery protection in test environment. |
| 36 | 38 |
config.action_controller.allow_forgery_protection = false |
| config/initializers/10-patches.rb | ||
|---|---|---|
| 49 | 49 |
end |
| 50 | 50 | |
| 51 | 51 |
class Resolver |
| 52 |
def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[])
|
|
| 53 |
locals = locals.map(&:to_s).sort!.freeze |
|
| 52 |
def find_all(name, prefix = nil, partial = false, details = {}, key = nil, locals = [])
|
|
| 53 |
if (details[:formats] & [:xml, :json]).any? |
|
| 54 |
details = details.dup |
|
| 55 |
details[:formats] = details[:formats].dup + [:api] |
|
| 54 | 56 | |
| 55 |
cached(key, [name, prefix, partial], details, locals) do |
|
| 56 |
if (details[:formats] & [:xml, :json]).any? |
|
| 57 |
details = details.dup |
|
| 58 |
details[:formats] = details[:formats].dup + [:api] |
|
| 59 |
end |
|
| 60 |
_find_all(name, prefix, partial, details, key, locals) |
|
| 57 |
key = ActionView::TemplateDetails::Requested.new(**details) if key |
|
| 61 | 58 |
end |
| 59 | ||
| 60 |
_find_all(name, prefix, partial, details, key, locals) |
|
| 62 | 61 |
end |
| 63 | 62 |
end |
| 64 | 63 |
end |
| ... | ... | |
| 69 | 68 |
module ActionView |
| 70 | 69 |
module Helpers |
| 71 | 70 |
module Tags |
| 72 |
class Base |
|
| 73 |
private |
|
| 74 |
alias :add_options_without_non_empty_blank_option :add_options |
|
| 71 |
SelectRenderer.prepend(Module.new do |
|
| 75 | 72 |
def add_options(option_tags, options, value = nil) |
| 76 |
if options[:include_blank] == true |
|
| 77 |
options = options.dup |
|
| 78 |
options[:include_blank] = ' '.html_safe |
|
| 73 |
if options.delete(:include_blank) |
|
| 74 |
options[:prompt] = ' '.html_safe |
|
| 79 | 75 |
end |
| 80 |
add_options_without_non_empty_blank_option(option_tags, options, value)
|
|
| 76 |
super
|
|
| 81 | 77 |
end |
| 82 |
end |
|
| 78 |
end)
|
|
| 83 | 79 |
end |
| 84 | 80 | |
| 85 | 81 |
module FormHelper |
| config/initializers/20-mime_types.rb | ||
|---|---|---|
| 1 | 1 |
# frozen_string_literal: true |
| 2 | 2 | |
| 3 | 3 |
# Add new mime types for use in respond_to blocks: |
| 4 |
Mime::SET << 'api' |
|
| config/initializers/zeitwerk.rb | ||
|---|---|---|
| 1 | 1 |
# frozen_string_literal: true |
| 2 | 2 | |
| 3 | 3 |
lib = Rails.root.join('lib/redmine')
|
| 4 |
Rails.autoloaders.main.push_dir lib, namespace: Redmine |
|
| 5 |
Rails.application.config.watchable_dirs[lib] = [:rb] |
|
| 6 | ||
| 7 | 4 |
IGNORE_LIST = [ |
| 8 | 5 |
'wiki_formatting/textile/redcloth3.rb', |
| 9 | 6 |
'core_ext.rb', |
| lib/redmine/plugin.rb | ||
|---|---|---|
| 467 | 467 |
else |
| 468 | 468 |
migrations |
| 469 | 469 |
end |
| 470 |
Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate |
|
| 470 |
Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
|
| 471 | 471 |
end |
| 472 | 472 | |
| 473 | 473 |
def down(target_version = nil) |
| ... | ... | |
| 477 | 477 |
else |
| 478 | 478 |
migrations |
| 479 | 479 |
end |
| 480 |
Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate |
|
| 480 |
Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
|
| 481 | 481 |
end |
| 482 | 482 | |
| 483 | 483 |
def run(direction, target_version) |
| 484 |
Migrator.new(direction, migrations, schema_migration, target_version).run |
|
| 484 |
Migrator.new(direction, migrations, schema_migration, internal_metadata, target_version).run
|
|
| 485 | 485 |
end |
| 486 | 486 | |
| 487 | 487 |
def open |
| 488 |
Migrator.new(:up, migrations, schema_migration) |
|
| 488 |
Migrator.new(:up, migrations, schema_migration, internal_metadata)
|
|
| 489 | 489 |
end |
| 490 | 490 | |
| 491 | 491 |
def current_version |
| ... | ... | |
| 510 | 510 |
# Delete migrations that don't match .. to_i will work because the number comes first |
| 511 | 511 |
@all_versions ||= {}
|
| 512 | 512 |
@all_versions[plugin.id.to_s] ||= begin |
| 513 |
sm_table = ::ActiveRecord::SchemaMigration.table_name
|
|
| 513 |
sm_table = ::ActiveRecord::Base.connection.schema_migration.table_name
|
|
| 514 | 514 |
migration_versions = ActiveRecord::Base.connection.select_values("SELECT version FROM #{sm_table}")
|
| 515 | 515 |
versions_by_plugins = migration_versions.group_by {|version| version.match(/-(.*)$/).try(:[], 1)}
|
| 516 | 516 |
@all_versions = versions_by_plugins.transform_values! {|versions| versions.map!(&:to_i).sort!}
|
| test/fixtures/issues.yml | ||
|---|---|---|
| 1 | 1 |
--- |
| 2 | 2 |
issues_001: |
| 3 |
created_on: <%= 3.days.ago.to_s(:db) %> |
|
| 3 |
created_on: <%= 3.days.ago.to_fs(:db) %>
|
|
| 4 | 4 |
project_id: 1 |
| 5 |
updated_on: <%= 1.day.ago.to_s(:db) %> |
|
| 5 |
updated_on: <%= 1.day.ago.to_fs(:db) %>
|
|
| 6 | 6 |
priority_id: 4 |
| 7 | 7 |
subject: Cannot print recipes |
| 8 | 8 |
id: 1 |
| ... | ... | |
| 13 | 13 |
assigned_to_id: |
| 14 | 14 |
author_id: 2 |
| 15 | 15 |
status_id: 1 |
| 16 |
start_date: <%= 1.day.ago.to_date.to_s(:db) %> |
|
| 17 |
due_date: <%= 10.day.from_now.to_date.to_s(:db) %> |
|
| 16 |
start_date: <%= 1.day.ago.to_date.to_fs(:db) %>
|
|
| 17 |
due_date: <%= 10.day.from_now.to_date.to_fs(:db) %>
|
|
| 18 | 18 |
estimated_hours: 200.0 |
| 19 | 19 |
root_id: 1 |
| 20 | 20 |
lft: 1 |
| ... | ... | |
| 34 | 34 |
assigned_to_id: 3 |
| 35 | 35 |
author_id: 2 |
| 36 | 36 |
status_id: 2 |
| 37 |
start_date: <%= 2.day.ago.to_date.to_s(:db) %> |
|
| 37 |
start_date: <%= 2.day.ago.to_date.to_fs(:db) %>
|
|
| 38 | 38 |
due_date: |
| 39 | 39 |
estimated_hours: 0.5 |
| 40 | 40 |
root_id: 2 |
| ... | ... | |
| 56 | 56 |
assigned_to_id: 3 |
| 57 | 57 |
author_id: 2 |
| 58 | 58 |
status_id: 1 |
| 59 |
start_date: <%= 15.day.ago.to_date.to_s(:db) %> |
|
| 60 |
due_date: <%= 5.day.ago.to_date.to_s(:db) %> |
|
| 59 |
start_date: <%= 15.day.ago.to_date.to_fs(:db) %>
|
|
| 60 |
due_date: <%= 5.day.ago.to_date.to_fs(:db) %>
|
|
| 61 | 61 |
estimated_hours: 1.0 |
| 62 | 62 |
root_id: 3 |
| 63 | 63 |
lft: 1 |
| 64 | 64 |
rgt: 2 |
| 65 | 65 |
issues_004: |
| 66 |
created_on: <%= 5.days.ago.to_s(:db) %> |
|
| 66 |
created_on: <%= 5.days.ago.to_fs(:db) %>
|
|
| 67 | 67 |
project_id: 2 |
| 68 |
updated_on: <%= 2.days.ago.to_s(:db) %> |
|
| 68 |
updated_on: <%= 2.days.ago.to_fs(:db) %>
|
|
| 69 | 69 |
priority_id: 4 |
| 70 | 70 |
subject: Issue on project 2 |
| 71 | 71 |
id: 4 |
| ... | ... | |
| 80 | 80 |
lft: 1 |
| 81 | 81 |
rgt: 2 |
| 82 | 82 |
issues_005: |
| 83 |
created_on: <%= 5.days.ago.to_s(:db) %> |
|
| 83 |
created_on: <%= 5.days.ago.to_fs(:db) %>
|
|
| 84 | 84 |
project_id: 3 |
| 85 |
updated_on: <%= 2.days.ago.to_s(:db) %> |
|
| 85 |
updated_on: <%= 2.days.ago.to_fs(:db) %>
|
|
| 86 | 86 |
priority_id: 4 |
| 87 | 87 |
subject: Subproject issue |
| 88 | 88 |
id: 5 |
| ... | ... | |
| 98 | 98 |
lft: 1 |
| 99 | 99 |
rgt: 2 |
| 100 | 100 |
issues_006: |
| 101 |
created_on: <%= 1.minute.ago.to_s(:db) %> |
|
| 101 |
created_on: <%= 1.minute.ago.to_fs(:db) %>
|
|
| 102 | 102 |
project_id: 5 |
| 103 |
updated_on: <%= 1.minute.ago.to_s(:db) %> |
|
| 103 |
updated_on: <%= 1.minute.ago.to_fs(:db) %>
|
|
| 104 | 104 |
priority_id: 4 |
| 105 | 105 |
subject: Issue of a private subproject |
| 106 | 106 |
id: 6 |
| ... | ... | |
| 111 | 111 |
assigned_to_id: |
| 112 | 112 |
author_id: 2 |
| 113 | 113 |
status_id: 1 |
| 114 |
start_date: <%= Date.today.to_s(:db) %> |
|
| 115 |
due_date: <%= 1.days.from_now.to_date.to_s(:db) %> |
|
| 114 |
start_date: <%= Date.today.to_fs(:db) %>
|
|
| 115 |
due_date: <%= 1.days.from_now.to_date.to_fs(:db) %>
|
|
| 116 | 116 |
root_id: 6 |
| 117 | 117 |
lft: 1 |
| 118 | 118 |
rgt: 2 |
| 119 | 119 |
issues_007: |
| 120 |
created_on: <%= 10.days.ago.to_s(:db) %> |
|
| 120 |
created_on: <%= 10.days.ago.to_fs(:db) %>
|
|
| 121 | 121 |
project_id: 1 |
| 122 |
updated_on: <%= 10.days.ago.to_s(:db) %> |
|
| 122 |
updated_on: <%= 10.days.ago.to_fs(:db) %>
|
|
| 123 | 123 |
priority_id: 5 |
| 124 | 124 |
subject: Issue due today |
| 125 | 125 |
id: 7 |
| ... | ... | |
| 130 | 130 |
assigned_to_id: |
| 131 | 131 |
author_id: 2 |
| 132 | 132 |
status_id: 1 |
| 133 |
start_date: <%= 10.days.ago.to_s(:db) %> |
|
| 134 |
due_date: <%= Date.today.to_s(:db) %> |
|
| 133 |
start_date: <%= 10.days.ago.to_fs(:db) %>
|
|
| 134 |
due_date: <%= Date.today.to_fs(:db) %>
|
|
| 135 | 135 |
lock_version: 0 |
| 136 | 136 |
root_id: 7 |
| 137 | 137 |
lft: 1 |
| 138 | 138 |
rgt: 2 |
| 139 | 139 |
issues_008: |
| 140 |
created_on: <%= 10.days.ago.to_s(:db) %> |
|
| 140 |
created_on: <%= 10.days.ago.to_fs(:db) %>
|
|
| 141 | 141 |
project_id: 1 |
| 142 |
updated_on: <%= 10.days.ago.to_s(:db) %> |
|
| 142 |
updated_on: <%= 10.days.ago.to_fs(:db) %>
|
|
| 143 | 143 |
priority_id: 5 |
| 144 | 144 |
subject: Closed issue |
| 145 | 145 |
id: 8 |
| ... | ... | |
| 156 | 156 |
root_id: 8 |
| 157 | 157 |
lft: 1 |
| 158 | 158 |
rgt: 2 |
| 159 |
closed_on: <%= 3.days.ago.to_s(:db) %> |
|
| 159 |
closed_on: <%= 3.days.ago.to_fs(:db) %>
|
|
| 160 | 160 |
issues_009: |
| 161 |
created_on: <%= 1.minute.ago.to_s(:db) %> |
|
| 161 |
created_on: <%= 1.minute.ago.to_fs(:db) %>
|
|
| 162 | 162 |
project_id: 5 |
| 163 |
updated_on: <%= 1.minute.ago.to_s(:db) %> |
|
| 163 |
updated_on: <%= 1.minute.ago.to_fs(:db) %>
|
|
| 164 | 164 |
priority_id: 5 |
| 165 | 165 |
subject: Blocked Issue |
| 166 | 166 |
id: 9 |
| ... | ... | |
| 171 | 171 |
assigned_to_id: |
| 172 | 172 |
author_id: 2 |
| 173 | 173 |
status_id: 1 |
| 174 |
start_date: <%= Date.today.to_s(:db) %> |
|
| 175 |
due_date: <%= 1.days.from_now.to_date.to_s(:db) %> |
|
| 174 |
start_date: <%= Date.today.to_fs(:db) %>
|
|
| 175 |
due_date: <%= 1.days.from_now.to_date.to_fs(:db) %>
|
|
| 176 | 176 |
root_id: 9 |
| 177 | 177 |
lft: 1 |
| 178 | 178 |
rgt: 2 |
| 179 | 179 |
issues_010: |
| 180 |
created_on: <%= 1.minute.ago.to_s(:db) %> |
|
| 180 |
created_on: <%= 1.minute.ago.to_fs(:db) %>
|
|
| 181 | 181 |
project_id: 5 |
| 182 |
updated_on: <%= 1.minute.ago.to_s(:db) %> |
|
| 182 |
updated_on: <%= 1.minute.ago.to_fs(:db) %>
|
|
| 183 | 183 |
priority_id: 5 |
| 184 | 184 |
subject: Issue Doing the Blocking |
| 185 | 185 |
id: 10 |
| ... | ... | |
| 190 | 190 |
assigned_to_id: |
| 191 | 191 |
author_id: 2 |
| 192 | 192 |
status_id: 1 |
| 193 |
start_date: <%= Date.today.to_s(:db) %> |
|
| 194 |
due_date: <%= 1.days.from_now.to_date.to_s(:db) %> |
|
| 193 |
start_date: <%= Date.today.to_fs(:db) %>
|
|
| 194 |
due_date: <%= 1.days.from_now.to_date.to_fs(:db) %>
|
|
| 195 | 195 |
root_id: 10 |
| 196 | 196 |
lft: 1 |
| 197 | 197 |
rgt: 2 |
| 198 | 198 |
issues_011: |
| 199 |
created_on: <%= 3.days.ago.to_s(:db) %> |
|
| 199 |
created_on: <%= 3.days.ago.to_fs(:db) %>
|
|
| 200 | 200 |
project_id: 1 |
| 201 |
updated_on: <%= 1.day.ago.to_s(:db) %> |
|
| 201 |
updated_on: <%= 1.day.ago.to_fs(:db) %>
|
|
| 202 | 202 |
priority_id: 5 |
| 203 | 203 |
subject: Closed issue on a closed version |
| 204 | 204 |
id: 11 |
| ... | ... | |
| 209 | 209 |
assigned_to_id: |
| 210 | 210 |
author_id: 2 |
| 211 | 211 |
status_id: 5 |
| 212 |
start_date: <%= 1.day.ago.to_date.to_s(:db) %> |
|
| 212 |
start_date: <%= 1.day.ago.to_date.to_fs(:db) %>
|
|
| 213 | 213 |
due_date: |
| 214 | 214 |
root_id: 11 |
| 215 | 215 |
lft: 1 |
| 216 | 216 |
rgt: 2 |
| 217 |
closed_on: <%= 1.day.ago.to_s(:db) %> |
|
| 217 |
closed_on: <%= 1.day.ago.to_fs(:db) %>
|
|
| 218 | 218 |
issues_012: |
| 219 |
created_on: <%= 3.days.ago.to_s(:db) %> |
|
| 219 |
created_on: <%= 3.days.ago.to_fs(:db) %>
|
|
| 220 | 220 |
project_id: 1 |
| 221 |
updated_on: <%= 1.day.ago.to_s(:db) %> |
|
| 221 |
updated_on: <%= 1.day.ago.to_fs(:db) %>
|
|
| 222 | 222 |
priority_id: 5 |
| 223 | 223 |
subject: Closed issue on a locked version |
| 224 | 224 |
id: 12 |
| ... | ... | |
| 229 | 229 |
assigned_to_id: |
| 230 | 230 |
author_id: 3 |
| 231 | 231 |
status_id: 5 |
| 232 |
start_date: <%= 1.day.ago.to_date.to_s(:db) %> |
|
| 232 |
start_date: <%= 1.day.ago.to_date.to_fs(:db) %>
|
|
| 233 | 233 |
due_date: |
| 234 | 234 |
root_id: 12 |
| 235 | 235 |
lft: 1 |
| 236 | 236 |
rgt: 2 |
| 237 |
closed_on: <%= 1.day.ago.to_s(:db) %> |
|
| 237 |
closed_on: <%= 1.day.ago.to_fs(:db) %>
|
|
| 238 | 238 |
issues_013: |
| 239 |
created_on: <%= 5.days.ago.to_s(:db) %> |
|
| 239 |
created_on: <%= 5.days.ago.to_fs(:db) %>
|
|
| 240 | 240 |
project_id: 3 |
| 241 |
updated_on: <%= 2.days.ago.to_s(:db) %> |
|
| 241 |
updated_on: <%= 2.days.ago.to_fs(:db) %>
|
|
| 242 | 242 |
priority_id: 4 |
| 243 | 243 |
subject: Subproject issue two |
| 244 | 244 |
id: 13 |
| ... | ... | |
| 254 | 254 |
rgt: 2 |
| 255 | 255 |
issues_014: |
| 256 | 256 |
id: 14 |
| 257 |
created_on: <%= 15.days.ago.to_s(:db) %> |
|
| 257 |
created_on: <%= 15.days.ago.to_fs(:db) %>
|
|
| 258 | 258 |
project_id: 3 |
| 259 |
updated_on: <%= 15.days.ago.to_s(:db) %> |
|
| 259 |
updated_on: <%= 15.days.ago.to_fs(:db) %>
|
|
| 260 | 260 |
priority_id: 5 |
| 261 | 261 |
subject: Private issue on public project |
| 262 | 262 |
fixed_version_id: |
| test/fixtures/journals.yml | ||
|---|---|---|
| 1 | 1 |
--- |
| 2 | 2 |
journals_001: |
| 3 |
created_on: <%= 2.days.ago.to_date.to_s(:db) %> |
|
| 4 |
updated_on: <%= 1.days.ago.to_date.to_s(:db) %> |
|
| 3 |
created_on: <%= 2.days.ago.to_date.to_fs(:db) %>
|
|
| 4 |
updated_on: <%= 1.days.ago.to_date.to_fs(:db) %>
|
|
| 5 | 5 |
notes: "Journal notes" |
| 6 | 6 |
id: 1 |
| 7 | 7 |
journalized_type: Issue |
| ... | ... | |
| 9 | 9 |
journalized_id: 1 |
| 10 | 10 |
updated_by_id: 1 |
| 11 | 11 |
journals_002: |
| 12 |
created_on: <%= 1.days.ago.to_date.to_s(:db) %> |
|
| 13 |
updated_on: <%= 1.days.ago.to_date.to_s(:db) %> |
|
| 12 |
created_on: <%= 1.days.ago.to_date.to_fs(:db) %>
|
|
| 13 |
updated_on: <%= 1.days.ago.to_date.to_fs(:db) %>
|
|
| 14 | 14 |
notes: "Some notes with Redmine links: #2, r2." |
| 15 | 15 |
id: 2 |
| 16 | 16 |
journalized_type: Issue |
| 17 | 17 |
user_id: 2 |
| 18 | 18 |
journalized_id: 1 |
| 19 | 19 |
journals_003: |
| 20 |
created_on: <%= 1.days.ago.to_date.to_s(:db) %> |
|
| 21 |
updated_on: <%= 1.days.ago.to_date.to_s(:db) %> |
|
| 20 |
created_on: <%= 1.days.ago.to_date.to_fs(:db) %>
|
|
| 21 |
updated_on: <%= 1.days.ago.to_date.to_fs(:db) %>
|
|
| 22 | 22 |
notes: "A comment with inline image: !picture.jpg! and a reference to #1 and r2." |
| 23 | 23 |
id: 3 |
| 24 | 24 |
journalized_type: Issue |
| 25 | 25 |
user_id: 2 |
| 26 | 26 |
journalized_id: 2 |
| 27 | 27 |
journals_004: |
| 28 |
created_on: <%= 1.days.ago.to_date.to_s(:db) %> |
|
| 29 |
updated_on: <%= 1.days.ago.to_date.to_s(:db) %> |
|
| 28 |
created_on: <%= 1.days.ago.to_date.to_fs(:db) %>
|
|
| 29 |
updated_on: <%= 1.days.ago.to_date.to_fs(:db) %>
|
|
| 30 | 30 |
notes: "A comment with a private version." |
| 31 | 31 |
id: 4 |
| 32 | 32 |
journalized_type: Issue |
| ... | ... | |
| 34 | 34 |
journalized_id: 6 |
| 35 | 35 |
journals_005: |
| 36 | 36 |
id: 5 |
| 37 |
created_on: <%= 1.days.ago.to_date.to_s(:db) %> |
|
| 38 |
updated_on: <%= 1.days.ago.to_date.to_s(:db) %> |
|
| 37 |
created_on: <%= 1.days.ago.to_date.to_fs(:db) %>
|
|
| 38 |
updated_on: <%= 1.days.ago.to_date.to_fs(:db) %>
|
|
| 39 | 39 |
notes: "A comment on a private issue." |
| 40 | 40 |
user_id: 2 |
| 41 | 41 |
journalized_type: Issue |
| test/fixtures/messages.yml | ||
|---|---|---|
| 45 | 45 |
parent_id: |
| 46 | 46 |
board_id: 1 |
| 47 | 47 |
messages_005: |
| 48 |
created_on: <%= 3.days.ago.to_date.to_s(:db) %> |
|
| 49 |
updated_on: <%= 3.days.ago.to_date.to_s(:db) %> |
|
| 48 |
created_on: <%= 3.days.ago.to_date.to_fs(:db) %>
|
|
| 49 |
updated_on: <%= 3.days.ago.to_date.to_fs(:db) %>
|
|
| 50 | 50 |
subject: 'RE: post 2' |
| 51 | 51 |
id: 5 |
| 52 | 52 |
replies_count: 0 |
| ... | ... | |
| 56 | 56 |
parent_id: 4 |
| 57 | 57 |
board_id: 1 |
| 58 | 58 |
messages_006: |
| 59 |
created_on: <%= 2.days.ago.to_date.to_s(:db) %> |
|
| 60 |
updated_on: <%= 2.days.ago.to_date.to_s(:db) %> |
|
| 59 |
created_on: <%= 2.days.ago.to_date.to_fs(:db) %>
|
|
| 60 |
updated_on: <%= 2.days.ago.to_date.to_fs(:db) %>
|
|
| 61 | 61 |
subject: 'RE: post 2' |
| 62 | 62 |
id: 6 |
| 63 | 63 |
replies_count: 0 |
| ... | ... | |
| 67 | 67 |
parent_id: 4 |
| 68 | 68 |
board_id: 1 |
| 69 | 69 |
messages_007: |
| 70 |
created_on: <%= 2.days.ago.to_date.to_s(:db) %> |
|
| 71 |
updated_on: <%= 2.days.ago.to_date.to_s(:db) %> |
|
| 70 |
created_on: <%= 2.days.ago.to_date.to_fs(:db) %>
|
|
| 71 |
updated_on: <%= 2.days.ago.to_date.to_fs(:db) %>
|
|
| 72 | 72 |
subject: 'Message on a private project' |
| 73 | 73 |
id: 7 |
| 74 | 74 |
replies_count: 0 |
| test/fixtures/versions.yml | ||
|---|---|---|
| 16 | 16 |
updated_on: 2006-07-19 21:00:33 +02:00 |
| 17 | 17 |
id: 2 |
| 18 | 18 |
description: Stable release |
| 19 |
effective_date: <%= 20.day.from_now.to_date.to_s(:db) %> |
|
| 19 |
effective_date: <%= 20.day.from_now.to_date.to_fs(:db) %>
|
|
| 20 | 20 |
status: locked |
| 21 | 21 |
sharing: 'none' |
| 22 | 22 |
wiki_page_title: ECookBookV1 |
| test/integration/layout_test.rb | ||
|---|---|---|
| 48 | 48 |
def test_top_menu_and_search_not_visible_when_login_required |
| 49 | 49 |
with_settings :login_required => '1' do |
| 50 | 50 |
get '/' |
| 51 |
assert_select "#top-menu > ul", 0 |
|
| 52 |
assert_select "#quick-search", 0
|
|
| 51 | ||
| 52 |
assert_equal response.status, 302
|
|
| 53 | 53 |
end |
| 54 | 54 |
end |
| 55 | 55 | |
| test/unit/query_test.rb | ||
|---|---|---|
| 1549 | 1549 |
query = IssueQuery.new(:name => '_') |
| 1550 | 1550 |
filter_name = "fixed_version.due_date" |
| 1551 | 1551 |
assert_include filter_name, query.available_filters.keys |
| 1552 |
query.filters = {filter_name => {:operator => '=', :values => [20.day.from_now.to_date.to_s(:db)]}}
|
|
| 1552 |
query.filters = {filter_name => {:operator => '=', :values => [20.day.from_now.to_date.to_fs(:db)]}}
|
|
| 1553 | 1553 |
issues = find_issues_with_query(query) |
| 1554 | 1554 |
assert_equal [2], issues.map(&:fixed_version_id).uniq.sort |
| 1555 | 1555 |
assert_equal [2, 12], issues.map(&:id).sort |
| 1556 | 1556 | |
| 1557 | 1557 |
query = IssueQuery.new(:name => '_') |
| 1558 |
query.filters = {filter_name => {:operator => '>=', :values => [21.day.from_now.to_date.to_s(:db)]}}
|
|
| 1558 |
query.filters = {filter_name => {:operator => '>=', :values => [21.day.from_now.to_date.to_fs(:db)]}}
|
|
| 1559 | 1559 |
assert_equal 0, find_issues_with_query(query).size |
| 1560 | 1560 |
end |
| 1561 | 1561 | |
| ... | ... | |
| 2962 | 2962 |
User.current.pref.update_attribute :time_zone, 'Hawaii' |
| 2963 | 2963 | |
| 2964 | 2964 |
# assume timestamps are stored as utc |
| 2965 |
ActiveRecord::Base.default_timezone = :utc
|
|
| 2965 |
ActiveRecord.default_timezone = :utc |
|
| 2966 | 2966 | |
| 2967 | 2967 |
from = Date.parse '2016-03-20' |
| 2968 | 2968 |
to = Date.parse '2016-03-22' |
| ... | ... | |
| 2973 | 2973 |
t = Time.new(2016, 3, 23, 9, 59, 59, 0).end_of_hour |
| 2974 | 2974 |
assert_equal "table.field > '#{Query.connection.quoted_date f}' AND table.field <= '#{Query.connection.quoted_date t}'", c
|
| 2975 | 2975 |
ensure |
| 2976 |
ActiveRecord::Base.default_timezone = :local # restore Redmine default
|
|
| 2976 |
ActiveRecord.default_timezone = :local # restore Redmine default |
|
| 2977 | 2977 |
end |
| 2978 | 2978 | |
| 2979 | 2979 |
def test_project_statement_with_closed_subprojects |
| test/unit/user_query_test.rb | ||
|---|---|---|
| 209 | 209 |
users = q.results_scope |
| 210 | 210 | |
| 211 | 211 |
assert_equal 2, users.size |
| 212 |
assert_equal [2, 1], users.ids
|
|
| 212 |
assert_equal [2, 1], users.pluck(:id)
|
|
| 213 | 213 |
end |
| 214 | 214 | |
| 215 | 215 |
def find_users_with_query(query) |