Revert revert unwanted in dev branch

This reverts commit b05a8f7b54.

The release/10 branch received a revert that was applied after changes
from dev unwillingly where merged into it. But when merging release/10.0
back into dev, that revert was also applied to dev where the changes are
indeed wanted. So we revert the revert for dev.
pull/7710/head
ulferts 5 years ago
parent 1d4ca2d02a
commit c83ba63640
No known key found for this signature in database
GPG Key ID: A205708DE1284017
  1. 4
      .codeclimate.yml
  2. 19
      Dangerfile
  3. 68
      Gemfile
  4. 407
      Gemfile.lock
  5. 2
      app/assets/javascripts/vendor/ckeditor/ckeditor.js
  6. 2
      app/assets/javascripts/vendor/ckeditor/ckeditor.js.map
  7. 2
      app/controllers/auth_sources_controller.rb
  8. 2
      app/controllers/colors_controller.rb
  9. 2
      app/controllers/concerns/omniauth_login.rb
  10. 2
      app/controllers/custom_styles_controller.rb
  11. 2
      app/controllers/enumerations_controller.rb
  12. 4
      app/controllers/forums_controller.rb
  13. 2
      app/controllers/groups_controller.rb
  14. 2
      app/controllers/highlighting_controller.rb
  15. 22
      app/controllers/projects_controller.rb
  16. 2
      app/controllers/statuses_controller.rb
  17. 2
      app/controllers/types_controller.rb
  18. 2
      app/controllers/wiki_controller.rb
  19. 9
      app/models/auth_source.rb
  20. 6
      app/models/category.rb
  21. 5
      app/models/enabled_module.rb
  22. 2
      app/models/journal.rb
  23. 10
      app/models/menu_item.rb
  24. 16
      app/models/project.rb
  25. 18
      app/models/queries/work_packages/columns/property_column.rb
  26. 6
      app/models/query.rb
  27. 103
      app/models/query/group_by.rb
  28. 14
      app/models/query/results.rb
  29. 7
      app/models/role.rb
  30. 8
      app/models/status.rb
  31. 14
      app/models/type.rb
  32. 7
      app/models/version.rb
  33. 2
      app/seeders/basic_data/role_seeder.rb
  34. 3
      app/services/authorization/abstract_query.rb
  35. 2
      app/views/layouts/admin.html.erb
  36. 2
      app/views/layouts/my.html.erb
  37. 2
      app/views/layouts/no_menu.html.erb
  38. 2
      app/workers/scm/storage_updater_job.rb
  39. 9
      codecov.yml
  40. 7
      config/application.rb
  41. 10
      config/cable.yml
  42. 2
      features/step_definitions/common_steps.rb
  43. 5
      features/support/env.rb
  44. 1
      lib/open_project/plugins/module_handler.rb
  45. 10
      lib/open_project/text_formatting/filters/sanitization_filter.rb
  46. 9
      lib/open_project/text_formatting/formats/base_formatter.rb
  47. 8
      lib/open_project/text_formatting/formats/markdown/formatter.rb
  48. 8
      lib/open_project/text_formatting/formats/plain/formatter.rb
  49. 2
      lib/open_project/version.rb
  50. 20
      lib/plugins/acts_as_watchable/lib/acts_as_watchable.rb
  51. 2
      modules/auth_saml/lib/open_project/auth_saml/engine.rb
  52. 2
      modules/backlogs/app/controllers/rb_application_controller.rb
  53. 2
      modules/backlogs/app/controllers/rb_sprints_controller.rb
  54. 2
      modules/bcf/lib/open_project/bcf/bcf_xml/issue_reader.rb
  55. 1
      modules/bcf/openproject-bcf.gemspec
  56. 2
      modules/documents/spec/controllers/documents_controller_spec.rb
  57. 4
      modules/grids/app/controllers/api/v3/grids/grids_api.rb
  58. 2
      modules/pdf_export/app/controllers/export_card_configurations_controller.rb
  59. 4
      modules/pdf_export/app/models/export_card_configuration.rb
  60. 2
      modules/reporting/openproject-reporting.gemspec
  61. 1
      modules/webhooks/spec/lib/hook_spec.rb
  62. 2
      spec/contracts/projects/shared_contract_examples.rb
  63. 2
      spec/controllers/custom_styles_controller_spec.rb
  64. 2
      spec/controllers/wiki_controller_spec.rb
  65. 4
      spec/factories/role_factory.rb
  66. 2
      spec/features/projects/destroy_spec.rb
  67. 14
      spec/features/projects/projects_index_spec.rb
  68. 6
      spec/features/repositories/create_repository_spec.rb
  69. 2
      spec/features/support/components/danger_zone.rb
  70. 4
      spec/features/users/index_spec.rb
  71. 16
      spec/features/users/my_spec.rb
  72. 7
      spec/features/work_packages/details/milestones_spec.rb
  73. 2
      spec/features/work_packages/edit_work_package_spec.rb
  74. 6
      spec/features/work_packages/tabs/activity_revisions_spec.rb
  75. 6
      spec/features/work_packages/tabs/activity_tab_spec.rb
  76. 2
      spec/features/work_packages/work_package_workflow_form_spec.rb
  77. 4
      spec/lib/open_project/configuration_spec.rb
  78. 2
      spec/models/application_record_spec.rb
  79. 4
      spec/models/project/storage_spec.rb
  80. 285
      spec/models/query/results_spec.rb
  81. 2
      spec/models/work_package/openproject_notifications_spec.rb
  82. 2
      spec/models/work_package/work_package_acts_as_watchable_spec.rb
  83. 2
      spec/models/work_package/work_package_notifications_spec.rb
  84. 7
      spec/rails_helper.rb
  85. 4
      spec/support/components/password_confirmation_dialog.rb
  86. 2
      spec/support/scm/relocate_repository.rb
  87. 8
      spec/support/shared/acts_as_watchable.rb
  88. 2
      spec/support/shared/with_settings.rb
  89. 6
      spec_legacy/unit/enumeration_spec.rb
  90. 2
      spec_legacy/unit/lib/redmine/hook_spec.rb
  91. 65
      spec_legacy/unit/query_spec.rb

@ -27,8 +27,10 @@ checks:
plugins:
rubocop:
enabled: true
# Codeclimate uses brakeman 4.3.1 which does not support rails 6
# Check https://docs.codeclimate.com/docs/brakeman for updates.
brakeman:
enabled: true
enabled: false
# as long as bundler-audit does not support bundler 2.0 we disable it
bundler-audit:
enabled: false

@ -1,3 +1,22 @@
# Fail if jasmine specs contain fdescribe or fit
fail("jasmine fdescribe left in tests") if `grep --include '*.spec.ts' -rP 'fdescribe|fit' frontend/src/`.length > 1
# Search for modified components not being made OnPush
git.modified_files
.select { |path| path.include?('frontend') && path.end_with?('.ts') }
.each do |path|
lines = File.readlines(path)
# Ignore non component files
component_line = lines.grep(/@Component/)[0]
next unless component_line
# Check for missing onPush
unless lines.grep(/changeDetection:\s+ChangeDetectionStrategy.OnPush/).length > 0
warn(
"Please use `ChangeDetectionStrategy.OnPush` for this component",
file: path,
line: lines.index(component_line) || 0
)
end
end

@ -32,10 +32,10 @@ ruby '~> 2.6.1'
gem 'actionpack-xml_parser', '~> 2.0.0'
gem 'activemodel-serializers-xml', '~> 1.0.1'
gem 'activerecord-import', '~> 0.28.1'
gem 'activerecord-import', '~> 1.0.2'
gem 'activerecord-session_store', '~> 1.1.0'
gem 'rails', '~> 5.2.2.1'
gem 'responders', '~> 2.4'
gem 'rails', '~> 6.0.0'
gem 'responders', '~> 3.0'
gem 'rdoc', '>= 2.4.2'
@ -50,15 +50,16 @@ gem 'warden-basic_auth', '~> 0.2.1'
gem 'will_paginate', '~> 3.1.7'
gem 'friendly_id', '~> 5.2.1'
# Replace once friendly_id release supports rails 6
gem 'friendly_id', git: 'https://github.com/norman/friendly_id', ref: '67422c04e1bfed4207b2a04826bc67ec0e231ce7'
gem 'acts_as_list', '~> 0.9.9'
gem 'acts_as_tree', '~> 2.8.0'
gem 'awesome_nested_set', '~> 3.1.3'
gem 'rubytree', git: 'https://github.com/dr0verride/RubyTree.git', ref: '06f53ee'
gem 'acts_as_tree', '~> 2.9.0'
gem 'awesome_nested_set', '~> 3.2.0'
gem 'rubytree', '~> 1.0.0'
gem 'typed_dag', '~> 2.0.2'
gem 'addressable', '~> 2.6.0'
gem 'addressable', '~> 2.7.0'
# Provide timezone info for TZInfo used by AR
gem 'tzinfo-data', '~> 1.2018.9'
@ -74,7 +75,7 @@ gem 'commonmarker', '~> 0.20.1'
# HTML pipeline for transformations on text formatter output
# such as sanitization or additional features
gem 'html-pipeline', '~> 2.8.0'
gem 'html-pipeline', '~> 2.12.0'
# Tasklist parsing and renderer
gem 'deckar01-task_list', '2.2.0'
# Requires escape-utils for faster escaping
@ -82,7 +83,7 @@ gem 'escape_utils', '~> 1.0'
# Syntax highlighting used in html-pipeline with rouge
gem 'rouge', '~> 3.1.1'
# HTML sanitization used for html-pipeline
gem 'sanitize', '~> 5.0.0'
gem 'sanitize', '~> 5.1.0'
# HTML autolinking for mails and urls (replaces autolink)
gem 'rinku', '~> 2.0.4'
# Version parsing with semver
@ -104,10 +105,10 @@ gem 'posix-spawn', '~> 0.3.13', require: false
gem 'bcrypt', '~> 3.1.6'
gem 'multi_json', '~> 1.13.1'
gem 'oj', '~> 3.7.0'
gem 'oj', '~> 3.9.1'
gem 'daemons'
gem 'delayed_job_active_record', '~> 4.1.1'
gem 'delayed_job_active_record', '~> 4.1.4'
gem 'rack-protection', '~> 2.0.0'
@ -115,13 +116,13 @@ gem 'rack-protection', '~> 2.0.0'
# It allows whitelisting, blacklisting, throttling, and tracking based
# on arbitrary properties of the request.
# https://github.com/kickstarter/rack-attack
gem 'rack-attack', '~> 5.4.2'
gem 'rack-attack', '~> 6.1.0'
# CSP headers
gem 'secure_headers', '~> 6.0.0'
gem 'secure_headers', '~> 6.1.1'
# Browser detection for incompatibility checks
gem 'browser', '~> 2.5.3'
gem 'browser', '~> 2.6.1'
# Providing health checks
gem 'okcomputer', '~> 1.17.3'
@ -133,7 +134,7 @@ gem 'lograge', '~> 0.10.0'
# catch exceptions and send them to any airbrake compatible backend
# don't require by default, instead load on-demand when actually configured
gem 'airbrake', '~> 8.0.1', require: false
gem 'airbrake', '~> 9.4.3', require: false
gem 'prawn', '~> 2.2'
gem 'prawn-table', '~> 0.2.2'
@ -146,18 +147,14 @@ gem 'meta-tags', '~> 2.11.0'
group :production do
# we use dalli as standard memcache client
# requires memcached 1.4+
# see https://github.clientom/mperham/dalli
gem 'dalli',
git: 'https://github.com/petergoldstein/dalli',
ref: '0ff39199b5e91c6dbdaabc7c085b81938d0f08d2'
gem 'dalli', '~> 2.7.10'
# Unicorn worker killer to restart unicorn child workers
gem 'unicorn-worker-killer', require: false
end
gem 'autoprefixer-rails', '~> 9.4.5'
# use until proper release no longer requiring sass exists
gem 'bourbon', git: 'https://github.com/sikachu/bourbon', ref: 'a12ca168e74d3468c80500b21b525a4e12a19ef9'
gem 'bourbon', '~> 6.0.0'
gem 'i18n-js', '~> 3.2.0'
gem 'sassc-rails', '~> 2.1.0'
gem 'sprockets', '~> 3.7.0'
@ -166,18 +163,18 @@ gem 'sprockets', '~> 3.7.0'
# also, better than thin since we can control worker concurrency.
gem 'unicorn'
gem 'puma', '~> 4.0.0' # used for development and optionally for production
gem 'puma', '~> 4.1.0' # used for development and optionally for production
gem 'nokogiri', '~> 1.10.4'
gem 'carrierwave', '~> 1.3.1'
gem 'fog-aws'
gem 'aws-sdk-core', '~> 3.46.0'
gem 'aws-sdk-core', '~> 3.66.0'
# File upload via fog + screenshots on travis
gem 'aws-sdk-s3', '~> 1.30.1'
gem 'aws-sdk-s3', '~> 1.48.0'
gem 'openproject-token', '~> 1.0.1'
gem 'openproject-token', '~> 1.0.2'
gem 'plaintext', '~> 0.3.2'
@ -199,16 +196,16 @@ group :test do
# Test prof provides factories from code
# and other niceties
gem 'test-prof', '~> 0.7.3'
gem 'test-prof', '~> 0.10.0'
gem 'cucumber', '~> 3.1.0'
gem 'cucumber-rails', '~> 1.6.0', require: false
gem 'cucumber-rails', '~> 1.8.0', require: false
gem 'database_cleaner', '~> 1.6'
gem 'rack_session_access'
gem 'rspec', '~> 3.8.0'
gem 'rspec-activemodel-mocks', '~> 1.1.0', git: 'https://github.com/rspec/rspec-activemodel-mocks'
# also add to development group, so "spec" rake task gets loaded
gem 'rspec-rails', '~> 3.8.1', group: :development
gem 'rspec-rails', '~> 4.0.0beta2', group: :development
# Retry failures within the same environment
gem 'retriable', '~> 3.1.1'
@ -219,7 +216,7 @@ group :test do
# brings back testing for 'assigns' and 'assert_template' extracted in rails 5
gem 'rails-controller-testing', '~> 1.0.2'
gem 'capybara', '~> 3.13.0'
gem 'capybara', '~> 3.29.0'
gem 'capybara-screenshot', '~> 1.0.17'
gem 'capybara-select2', git: 'https://github.com/goodwill/capybara-select2', ref: '585192e'
gem 'webdrivers', '~> 4.1.2', require: false
@ -227,14 +224,13 @@ group :test do
gem 'fuubar', '~> 2.3.2'
gem 'timecop', '~> 0.9.0'
gem 'webmock', '~> 3.5.0', require: false
gem 'webmock', '~> 3.7.2', require: false
gem 'equivalent-xml', '~> 0.6'
gem 'json_spec', '~> 1.1.4'
gem 'shoulda-matchers', '~> 3.1', require: nil
gem 'simplecov', '~> 0.16.0', require: false
gem 'parallel_tests', '~> 2.27.1'
gem 'parallel_tests', '~> 2.29.2'
end
group :ldap do
@ -261,7 +257,7 @@ group :development, :test do
gem 'ruby-prof', require: false
gem 'stackprof', require: false
gem 'pry-byebug', '~> 3.6.0', platforms: [:mri]
gem 'pry-byebug', '~> 3.7.0', platforms: [:mri]
gem 'pry-rails', '~> 0.3.6'
gem 'pry-rescue', '~> 1.5.0'
gem 'pry-stack_explorer', '~> 0.4.9.2'
@ -274,7 +270,7 @@ group :development, :test do
gem 'danger-brakeman'
end
gem 'bootsnap', '~> 1.3.2', require: false
gem 'bootsnap', '~> 1.4.5', require: false
# API gems
gem 'grape', '~> 1.2.3'
@ -289,7 +285,7 @@ platforms :mri, :mingw, :x64_mingw do
end
# Support application loading when no database exists yet.
gem 'activerecord-nulldb-adapter', '~> 0.3.9'
gem 'activerecord-nulldb-adapter', '~> 0.4.0'
end
group :opf_plugins do

@ -6,14 +6,6 @@ GIT
doorkeeper (5.0.2)
railties (>= 4.2)
GIT
remote: https://github.com/dr0verride/RubyTree.git
revision: 06f53ee78cc2a48377c1bd177d3bc83c1504701c
ref: 06f53ee
specs:
rubytree (0.9.7)
json (~> 1.8)
GIT
remote: https://github.com/finnlabs/omniauth-openid-connect.git
revision: 9e7fd0e7bd36d40451c6b3c2ea641e8d237c295d
@ -47,6 +39,14 @@ GIT
capybara
rspec
GIT
remote: https://github.com/norman/friendly_id
revision: 67422c04e1bfed4207b2a04826bc67ec0e231ce7
ref: 67422c04e1bfed4207b2a04826bc67ec0e231ce7
specs:
friendly_id (5.2.5)
activerecord (>= 4.0.0)
GIT
remote: https://github.com/opf/omniauth
revision: fe862f986b2e846e291784d2caa3d90a658c67f0
@ -66,13 +66,6 @@ GIT
mixlib-shellout (~> 2.1.0)
rubyzip
GIT
remote: https://github.com/petergoldstein/dalli
revision: 0ff39199b5e91c6dbdaabc7c085b81938d0f08d2
ref: 0ff39199b5e91c6dbdaabc7c085b81938d0f08d2
specs:
dalli (2.7.9)
GIT
remote: https://github.com/rspec/rspec-activemodel-mocks
revision: 6136a778f8b21f4f45f6b4ad5c2e2533e6d4ddc6
@ -82,14 +75,6 @@ GIT
activesupport (>= 3.0)
rspec-mocks (>= 2.99, < 4.0)
GIT
remote: https://github.com/sikachu/bourbon
revision: a12ca168e74d3468c80500b21b525a4e12a19ef9
ref: a12ca168e74d3468c80500b21b525a4e12a19ef9
specs:
bourbon (5.1.0)
thor (~> 0.19)
PATH
remote: modules/auth_plugins
specs:
@ -121,7 +106,6 @@ PATH
specs:
openproject-bcf (1.0.0)
activerecord-import
rails (~> 5)
rubyzip (~> 1.2)
PATH
@ -221,7 +205,7 @@ PATH
remote: modules/reporting
specs:
openproject-reporting (1.0.0)
jquery-tablesorter (~> 1.25.5)
jquery-tablesorter (~> 1.27.0)
openproject-costs
reporting_engine
@ -248,48 +232,60 @@ GEM
remote: https://rubygems.org/
specs:
Ascii85 (1.0.3)
actioncable (5.2.2.1)
actionpack (= 5.2.2.1)
actioncable (6.0.0)
actionpack (= 6.0.0)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailer (5.2.2.1)
actionpack (= 5.2.2.1)
actionview (= 5.2.2.1)
activejob (= 5.2.2.1)
actionmailbox (6.0.0)
actionpack (= 6.0.0)
activejob (= 6.0.0)
activerecord (= 6.0.0)
activestorage (= 6.0.0)
activesupport (= 6.0.0)
mail (>= 2.7.1)
actionmailer (6.0.0)
actionpack (= 6.0.0)
actionview (= 6.0.0)
activejob (= 6.0.0)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (5.2.2.1)
actionview (= 5.2.2.1)
activesupport (= 5.2.2.1)
actionpack (6.0.0)
actionview (= 6.0.0)
activesupport (= 6.0.0)
rack (~> 2.0)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actionpack-xml_parser (2.0.1)
actionpack (>= 5.0)
railties (>= 5.0)
actionview (5.2.2.1)
activesupport (= 5.2.2.1)
actiontext (6.0.0)
actionpack (= 6.0.0)
activerecord (= 6.0.0)
activestorage (= 6.0.0)
activesupport (= 6.0.0)
nokogiri (>= 1.8.5)
actionview (6.0.0)
activesupport (= 6.0.0)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
activejob (5.2.2.1)
activesupport (= 5.2.2.1)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (6.0.0)
activesupport (= 6.0.0)
globalid (>= 0.3.6)
activemodel (5.2.2.1)
activesupport (= 5.2.2.1)
activemodel (6.0.0)
activesupport (= 6.0.0)
activemodel-serializers-xml (1.0.2)
activemodel (> 5.x)
activesupport (> 5.x)
builder (~> 3.1)
activerecord (5.2.2.1)
activemodel (= 5.2.2.1)
activesupport (= 5.2.2.1)
arel (>= 9.0)
activerecord-import (0.28.1)
activerecord (6.0.0)
activemodel (= 6.0.0)
activesupport (= 6.0.0)
activerecord-import (1.0.2)
activerecord (>= 3.2)
activerecord-nulldb-adapter (0.3.9)
activerecord-nulldb-adapter (0.4.0)
activerecord (>= 2.0.0)
activerecord-session_store (1.1.1)
actionpack (>= 4.0)
@ -297,74 +293,78 @@ GEM
multi_json (~> 1.11, >= 1.11.2)
rack (>= 1.5.2, < 3)
railties (>= 4.0)
activestorage (5.2.2.1)
actionpack (= 5.2.2.1)
activerecord (= 5.2.2.1)
activestorage (6.0.0)
actionpack (= 6.0.0)
activejob (= 6.0.0)
activerecord (= 6.0.0)
marcel (~> 0.3.1)
activesupport (5.2.2.1)
activesupport (6.0.0)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.1, >= 2.1.8)
acts_as_list (0.9.19)
activerecord (>= 3.0)
acts_as_tree (2.8.0)
acts_as_tree (2.9.0)
activerecord (>= 3.0.0)
addressable (2.6.0)
public_suffix (>= 2.0.2, < 4.0)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
aes_key_wrap (1.0.1)
afm (0.2.2)
airbrake (8.0.1)
airbrake-ruby (~> 3.0)
airbrake-ruby (3.1.0)
tdigest (= 0.1.1)
arel (9.0.0)
airbrake (9.4.3)
airbrake-ruby (~> 4.6)
airbrake-ruby (4.6.0)
rbtree3 (~> 0.5)
ast (2.4.0)
attr_required (1.0.1)
autoprefixer-rails (9.4.7)
execjs
awesome_nested_set (3.1.4)
activerecord (>= 4.0.0, < 5.3)
aws-eventstream (1.0.1)
aws-partitions (1.136.0)
aws-sdk-core (3.46.0)
aws-eventstream (~> 1.0)
awesome_nested_set (3.2.0)
activerecord (>= 4.0.0, < 7.0)
aws-eventstream (1.0.3)
aws-partitions (1.208.0)
aws-sdk-core (3.66.0)
aws-eventstream (~> 1.0, >= 1.0.2)
aws-partitions (~> 1.0)
aws-sigv4 (~> 1.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.13.0)
aws-sdk-core (~> 3, >= 3.39.0)
aws-sigv4 (~> 1.0)
aws-sdk-s3 (1.30.1)
aws-sdk-core (~> 3, >= 3.39.0)
aws-sdk-kms (1.24.0)
aws-sdk-core (~> 3, >= 3.61.1)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.48.0)
aws-sdk-core (~> 3, >= 3.61.1)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.0)
aws-sigv4 (~> 1.1)
aws-sdk-sns (1.1.0)
aws-sdk-core (~> 3)
aws-sigv4 (~> 1.0)
aws-sigv4 (1.0.3)
aws-sigv4 (1.1.0)
aws-eventstream (~> 1.0, >= 1.0.2)
axiom-types (0.1.1)
descendants_tracker (~> 0.0.4)
ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1)
backports (3.11.4)
bcrypt (3.1.12)
bcrypt (3.1.13)
bindata (2.4.4)
binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1)
bootsnap (1.3.2)
bootsnap (1.4.5)
msgpack (~> 1.0)
bourbon (6.0.0)
thor (~> 0.19)
brakeman (4.6.1)
browser (2.5.3)
browser (2.6.1)
builder (3.2.3)
byebug (10.0.2)
capybara (3.13.2)
byebug (11.0.1)
capybara (3.29.0)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (~> 1.2)
regexp_parser (~> 1.5)
xpath (~> 3.2)
capybara-screenshot (1.0.22)
capybara (>= 1.0, < 4)
@ -419,15 +419,16 @@ GEM
cucumber-tag_expressions (~> 1.1.0)
gherkin (~> 5.0)
cucumber-expressions (6.0.1)
cucumber-rails (1.6.0)
capybara (>= 1.1.2, < 4)
cucumber-rails (1.8.0)
capybara (>= 2.12, < 4)
cucumber (>= 3.0.2, < 4)
mime-types (>= 1.17, < 4)
mime-types (>= 2.0, < 4)
nokogiri (~> 1.8)
railties (>= 4, < 6)
railties (>= 4.2, < 7)
cucumber-tag_expressions (1.1.1)
cucumber-wire (0.0.1)
daemons (1.3.1)
dalli (2.7.10)
danger (6.0.9)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
@ -457,10 +458,10 @@ GEM
declarative-builder (0.1.0)
declarative-option (< 0.2.0)
declarative-option (0.1.0)
delayed_job (4.1.5)
activesupport (>= 3.0, < 5.3)
delayed_job_active_record (4.1.3)
activerecord (>= 3.0, < 5.3)
delayed_job (4.1.8)
activesupport (>= 3.0, < 6.1)
delayed_job_active_record (4.1.4)
activerecord (>= 3.0, < 6.1)
delayed_job (>= 3.0, < 5)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
@ -471,7 +472,6 @@ GEM
declarative-option (< 0.2.0)
representable (>= 2.4.0, <= 3.1.0)
uber (< 0.2.0)
docile (1.3.1)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
equalizer (0.0.11)
@ -515,8 +515,6 @@ GEM
fog-core
nokogiri (>= 1.5.11, < 2.0.0)
formatador (0.2.5)
friendly_id (5.2.5)
activerecord (>= 4.0.0)
fuubar (2.3.2)
rspec-core (~> 3.0)
ruby-progressbar (~> 1.4)
@ -529,7 +527,7 @@ GEM
actionpack (>= 3.0)
multi_json
request_store (>= 1.0)
grape (1.2.3)
grape (1.2.4)
activesupport
builder
mustermann-grape (~> 1.0.0)
@ -537,10 +535,10 @@ GEM
rack-accept
virtus (>= 1.0.0)
gravatar_image_tag (1.2.0)
hashdiff (0.3.8)
hashdiff (1.0.0)
hashery (2.1.2)
hashie (3.6.0)
html-pipeline (2.8.3)
html-pipeline (2.12.0)
activesupport (>= 2)
nokogiri (>= 1.4)
htmldiff (0.0.1)
@ -558,11 +556,11 @@ GEM
interception (0.5)
ipaddress (0.8.3)
iso8601 (0.12.1)
jaro_winkler (1.5.2)
jaro_winkler (1.5.3)
jmespath (1.4.0)
jquery-tablesorter (1.25.5)
railties (>= 3.2, < 6)
json (1.8.6)
jquery-tablesorter (1.27.0)
railties (~> 6.0.0, >= 3.2)
json (2.2.0)
json-jwt (1.10.0)
activesupport (>= 4.2)
aes_key_wrap
@ -610,12 +608,12 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
mimemagic (0.3.3)
mini_mime (1.0.1)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
minisyntax (0.2.5)
minitest (5.11.3)
mixlib-shellout (2.1.0)
msgpack (1.2.6)
msgpack (1.3.1)
multi_json (1.13.1)
multi_test (0.1.2)
multipart-post (2.1.1)
@ -625,8 +623,8 @@ GEM
nap (1.1.0)
net-ldap (0.16.1)
netrc (0.11.0)
newrelic_rpm (6.0.0.351)
nio4r (2.3.1)
newrelic_rpm (6.6.0.358)
nio4r (2.5.1)
no_proxy_fix (0.1.2)
nokogiri (1.10.4)
mini_portile2 (~> 2.4.0)
@ -634,8 +632,8 @@ GEM
nokogiri (~> 1.8, >= 1.8.4)
octokit (4.14.0)
sawyer (~> 0.8.0, >= 0.5.3)
oj (3.7.8)
okcomputer (1.17.3)
oj (3.9.1)
okcomputer (1.17.4)
omniauth-saml (1.10.1)
omniauth (~> 1.3, >= 1.3.2)
ruby-saml (~> 1.7)
@ -650,14 +648,13 @@ GEM
validate_email
validate_url
webfinger (>= 1.0.1)
openproject-token (1.0.1)
activemodel (~> 5.0)
parallel (1.13.0)
parallel_tests (2.27.1)
openproject-token (1.0.2)
parallel (1.17.0)
parallel_tests (2.29.2)
parallel
parser (2.6.0.0)
parser (2.6.4.0)
ast (~> 2.4.0)
passenger (6.0.1)
passenger (6.0.2)
rack
rake (>= 0.8.1)
pdf-core (0.7.0)
@ -675,7 +672,6 @@ GEM
nokogiri (~> 1.10, >= 1.10.4)
rubyzip (~> 1.2.1)
posix-spawn (0.3.13)
powerpack (0.1.2)
prawn (2.2.2)
pdf-core (~> 0.7.0)
ttfunk (~> 1.5)
@ -684,8 +680,8 @@ GEM
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
pry-byebug (3.6.0)
byebug (~> 10.0)
pry-byebug (3.7.0)
byebug (~> 11.0)
pry (~> 0.10)
pry-rails (0.3.9)
pry (>= 0.10.4)
@ -695,13 +691,13 @@ GEM
pry-stack_explorer (0.4.9.3)
binding_of_caller (>= 0.7)
pry (>= 0.9.11)
public_suffix (3.0.3)
puma (4.0.0)
public_suffix (4.0.1)
puma (4.1.0)
nio4r (~> 2.0)
rack (2.0.6)
rack (2.0.7)
rack-accept (0.4.5)
rack (>= 0.4)
rack-attack (5.4.2)
rack-attack (6.1.0)
rack (>= 1.0, < 3)
rack-mini-profiler (1.0.1)
rack (>= 1.2.0)
@ -711,25 +707,27 @@ GEM
httpclient
json-jwt (>= 1.9.0)
rack
rack-protection (2.0.5)
rack-protection (2.0.7)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rack_session_access (0.2.0)
builder (>= 2.0.0)
rack (>= 1.0.0)
rails (5.2.2.1)
actioncable (= 5.2.2.1)
actionmailer (= 5.2.2.1)
actionpack (= 5.2.2.1)
actionview (= 5.2.2.1)
activejob (= 5.2.2.1)
activemodel (= 5.2.2.1)
activerecord (= 5.2.2.1)
activestorage (= 5.2.2.1)
activesupport (= 5.2.2.1)
rails (6.0.0)
actioncable (= 6.0.0)
actionmailbox (= 6.0.0)
actionmailer (= 6.0.0)
actionpack (= 6.0.0)
actiontext (= 6.0.0)
actionview (= 6.0.0)
activejob (= 6.0.0)
activemodel (= 6.0.0)
activerecord (= 6.0.0)
activestorage (= 6.0.0)
activesupport (= 6.0.0)
bundler (>= 1.3.0)
railties (= 5.2.2.1)
railties (= 6.0.0)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.4)
actionpack (>= 5.0.1.x)
@ -738,23 +736,23 @@ GEM
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.0.4)
rails-html-sanitizer (1.2.0)
loofah (~> 2.2, >= 2.2.2)
rails_12factor (0.0.3)
rails_serve_static_assets
rails_stdout_logging
rails_serve_static_assets (0.0.5)
rails_stdout_logging (0.0.5)
railties (5.2.2.1)
actionpack (= 5.2.2.1)
activesupport (= 5.2.2.1)
railties (6.0.0)
actionpack (= 6.0.0)
activesupport (= 6.0.0)
method_source
rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0)
thor (>= 0.20.3, < 2.0)
rainbow (3.0.0)
raindrops (0.19.0)
rake (12.3.2)
rbtree (0.4.2)
rake (12.3.3)
rbtree3 (0.5.0)
rdoc (6.1.1)
recaptcha (5.1.0)
json
@ -765,16 +763,16 @@ GEM
reform-rails (0.1.7)
activemodel (>= 3.2)
reform (>= 2.2.0)
regexp_parser (1.3.0)
regexp_parser (1.6.0)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
request_store (1.4.1)
rack (>= 1.4)
responders (2.4.1)
actionpack (>= 4.2.0, < 6.0)
railties (>= 4.2.0, < 6.0)
responders (3.0.0)
actionpack (>= 5.0)
railties (>= 5.0)
rest-client (2.0.2)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
@ -797,25 +795,24 @@ GEM
rspec-mocks (3.8.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-rails (3.8.2)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-support (~> 3.8.0)
rspec-rails (4.0.0.beta2)
actionpack (>= 4.2)
activesupport (>= 4.2)
railties (>= 4.2)
rspec-core (~> 3.8)
rspec-expectations (~> 3.8)
rspec-mocks (~> 3.8)
rspec-support (~> 3.8)
rspec-retry (0.6.1)
rspec-core (> 3.3)
rspec-support (3.8.0)
rubocop (0.63.1)
rubocop (0.74.0)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.5, != 2.5.1.1)
powerpack (~> 0.1)
parser (>= 2.6)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.4.0)
unicode-display_width (>= 1.4.0, < 1.7)
ruby-duration (3.2.3)
activesupport (>= 3.0.0)
i18n
@ -823,14 +820,17 @@ GEM
ruby-enum (0.7.2)
i18n
ruby-ole (1.2.12.2)
ruby-prof (0.17.0)
ruby-progressbar (1.10.0)
ruby-prof (1.0.0)
ruby-progressbar (1.10.1)
ruby-rc4 (0.1.5)
ruby-saml (1.9.0)
nokogiri (>= 1.5.10)
rubytree (1.0.0)
json (~> 2.1)
structured_warnings (~> 0.3)
rubyzip (1.2.2)
safe_yaml (1.0.4)
sanitize (5.0.0)
safe_yaml (1.0.5)
sanitize (5.1.0)
crass (~> 1.0.2)
nokogiri (>= 1.8.0)
nokogumbo (~> 2.0)
@ -846,8 +846,7 @@ GEM
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
secure_headers (6.0.0)
useragent (>= 0.15.0)
secure_headers (6.1.1)
selenium-webdriver (3.141.0)
childprocess (~> 0.5)
rubyzip (~> 1.2, >= 1.2.2)
@ -855,15 +854,9 @@ GEM
shoulda-context (1.2.2)
shoulda-matchers (3.1.3)
activesupport (>= 4.0.0)
simplecov (0.16.1)
docile (~> 1.1)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
spreadsheet (0.8.9)
ruby-ole (>= 1.0)
spring (2.0.2)
activesupport (>= 4.2)
spring (2.1.0)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
sprockets (3.7.2)
@ -875,6 +868,7 @@ GEM
sprockets (>= 3.0.0)
stackprof (0.2.12)
stringex (2.8.5)
structured_warnings (0.4.0)
svg-graph (2.1.3)
swd (1.1.2)
activesupport (>= 3)
@ -882,12 +876,10 @@ GEM
httpclient (>= 2.4)
sys-filesystem (1.2.0)
ffi
tdigest (0.1.1)
rbtree (~> 0.4.2)
temple (0.8.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
test-prof (0.7.3)
test-prof (0.10.0)
thin (1.7.2)
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0, >= 1.0.4)
@ -907,14 +899,13 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.7.5)
unicode-display_width (1.4.1)
unicorn (5.4.1)
unicode-display_width (1.6.0)
unicorn (5.5.1)
kgio (~> 2.6)
raindrops (~> 0.7)
unicorn-worker-killer (0.4.4)
get_process_mem (~> 0)
unicorn (>= 4, < 6)
useragent (0.16.10)
validate_email (0.1.6)
activemodel (>= 3.0)
mail (>= 2.2.5)
@ -937,16 +928,17 @@ GEM
webfinger (1.1.0)
activesupport
httpclient (>= 2.4)
webmock (3.5.1)
webmock (3.7.2)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
websocket-driver (0.7.0)
hashdiff (>= 0.4.0, < 2.0.0)
websocket-driver (0.7.1)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3)
will_paginate (3.1.7)
websocket-extensions (0.1.4)
will_paginate (3.1.8)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.1.10)
PLATFORMS
ruby
@ -954,23 +946,23 @@ PLATFORMS
DEPENDENCIES
actionpack-xml_parser (~> 2.0.0)
activemodel-serializers-xml (~> 1.0.1)
activerecord-import (~> 0.28.1)
activerecord-nulldb-adapter (~> 0.3.9)
activerecord-import (~> 1.0.2)
activerecord-nulldb-adapter (~> 0.4.0)
activerecord-session_store (~> 1.1.0)
acts_as_list (~> 0.9.9)
acts_as_tree (~> 2.8.0)
addressable (~> 2.6.0)
airbrake (~> 8.0.1)
acts_as_tree (~> 2.9.0)
addressable (~> 2.7.0)
airbrake (~> 9.4.3)
autoprefixer-rails (~> 9.4.5)
awesome_nested_set (~> 3.1.3)
aws-sdk-core (~> 3.46.0)
aws-sdk-s3 (~> 1.30.1)
awesome_nested_set (~> 3.2.0)
aws-sdk-core (~> 3.66.0)
aws-sdk-s3 (~> 1.48.0)
bcrypt (~> 3.1.6)
bootsnap (~> 1.3.2)
bourbon!
bootsnap (~> 1.4.5)
bourbon (~> 6.0.0)
brakeman (~> 4.6.1)
browser (~> 2.5.3)
capybara (~> 3.13.0)
browser (~> 2.6.1)
capybara (~> 3.29.0)
capybara-screenshot (~> 1.0.17)
capybara-select2!
carrierwave (~> 1.3.1)
@ -978,16 +970,16 @@ DEPENDENCIES
cells-rails (~> 0.0.9)
commonmarker (~> 0.20.1)
cucumber (~> 3.1.0)
cucumber-rails (~> 1.6.0)
cucumber-rails (~> 1.8.0)
daemons
dalli!
dalli (~> 2.7.10)
danger (~> 6.0.9)
danger-brakeman
dashboards!
database_cleaner (~> 1.6)
date_validator (~> 0.9.0)
deckar01-task_list (= 2.2.0)
delayed_job_active_record (~> 4.1.1)
delayed_job_active_record (~> 4.1.4)
doorkeeper!
equivalent-xml (~> 0.6)
escape_utils (~> 1.0)
@ -996,12 +988,12 @@ DEPENDENCIES
faker
flamegraph
fog-aws
friendly_id (~> 5.2.1)
friendly_id!
fuubar (~> 2.3.2)
gon (~> 6.2.1)
grape (~> 1.2.3)
grids!
html-pipeline (~> 2.8.0)
html-pipeline (~> 2.12.0)
htmldiff
i18n-js (~> 3.2.0)
json_spec (~> 1.1.4)
@ -1016,7 +1008,7 @@ DEPENDENCIES
net-ldap (~> 0.16.0)
newrelic_rpm
nokogiri (~> 1.10.4)
oj (~> 3.7.0)
oj (~> 3.9.1)
okcomputer (~> 1.17.3)
omniauth!
omniauth-openid-connect!
@ -1039,30 +1031,30 @@ DEPENDENCIES
openproject-pdf_export!
openproject-recaptcha!
openproject-reporting!
openproject-token (~> 1.0.1)
openproject-token (~> 1.0.2)
openproject-translations!
openproject-two_factor_authentication!
openproject-webhooks!
openproject-xls_export!
overviews!
parallel_tests (~> 2.27.1)
parallel_tests (~> 2.29.2)
passenger (~> 6.0.1)
pg (~> 1.1.0)
plaintext (~> 0.3.2)
posix-spawn (~> 0.3.13)
prawn (~> 2.2)
prawn-table (~> 0.2.2)
pry-byebug (~> 3.6.0)
pry-byebug (~> 3.7.0)
pry-rails (~> 0.3.6)
pry-rescue (~> 1.5.0)
pry-stack_explorer (~> 0.4.9.2)
puma (~> 4.0.0)
rack-attack (~> 5.4.2)
puma (~> 4.1.0)
rack-attack (~> 6.1.0)
rack-mini-profiler
rack-protection (~> 2.0.0)
rack-test (~> 1.1.0)
rack_session_access
rails (~> 5.2.2.1)
rails (~> 6.0.0)
rails-controller-testing (~> 1.0.2)
rails_12factor
rdoc (>= 2.4.2)
@ -1070,7 +1062,7 @@ DEPENDENCIES
reform-rails (~> 0.1.7)
reporting_engine!
request_store (~> 1.4.1)
responders (~> 2.4)
responders (~> 3.0)
rest-client (~> 2.0)
retriable (~> 3.1.1)
rinku (~> 2.0.4)
@ -1079,21 +1071,20 @@ DEPENDENCIES
rspec (~> 3.8.0)
rspec-activemodel-mocks (~> 1.1.0)!
rspec-example_disabler!
rspec-rails (~> 3.8.1)
rspec-rails (~> 4.0.0beta2)
rspec-retry (~> 0.6.1)
rubocop
ruby-duration (~> 3.2.0)
ruby-prof
ruby-progressbar (~> 1.10.0)
rubytree!
sanitize (~> 5.0.0)
rubytree (~> 1.0.0)
sanitize (~> 5.1.0)
sassc-rails (~> 2.1.0)
secure_headers (~> 6.0.0)
secure_headers (~> 6.1.1)
selenium-webdriver (~> 3.14)
semantic (~> 1.6.1)
shoulda-context (~> 1.2)
shoulda-matchers (~> 3.1)
simplecov (~> 0.16.0)
spring
spring-commands-rspec
sprockets (~> 3.7.0)
@ -1101,7 +1092,7 @@ DEPENDENCIES
stringex (~> 2.8.5)
svg-graph (~> 2.1.0)
sys-filesystem (~> 1.2.0)
test-prof (~> 0.7.3)
test-prof (~> 0.10.0)
thin (~> 1.7.2)
timecop (~> 0.9.0)
typed_dag (~> 2.0.2)
@ -1111,7 +1102,7 @@ DEPENDENCIES
warden (~> 1.2)
warden-basic_auth (~> 0.2.1)
webdrivers (~> 4.1.2)
webmock (~> 3.5.0)
webmock (~> 3.7.2)
will_paginate (~> 3.1.7)
RUBY VERSION

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -66,7 +66,7 @@ class AuthSourcesController < ApplicationController
updated = permitted_params.auth_source
updated.delete :account_password if updated[:account_password].blank?
if @auth_source.update_attributes updated
if @auth_source.update updated
flash[:notice] = l(:notice_successful_update)
redirect_to action: 'index'
else

@ -76,7 +76,7 @@ class ColorsController < ApplicationController
def update
@color = Color.find(params[:id])
if @color.update_attributes(permitted_params.color)
if @color.update(permitted_params.color)
flash[:notice] = l(:notice_successful_update)
redirect_to colors_path
else

@ -167,7 +167,7 @@ module Concerns::OmniauthLogin
return if handle_omniauth_registration_expired(auth)
fill_user_fields_from_omniauth(user, auth)
user.update_attributes(permitted_params.user_register_via_omniauth)
user.update(permitted_params.user_register_via_omniauth)
opts = {
omni_auth_hash: auth

@ -53,7 +53,7 @@ class CustomStylesController < ApplicationController
def update
@custom_style = CustomStyle.current
if @custom_style.update_attributes(custom_style_params)
if @custom_style.update(custom_style_params)
redirect_to custom_style_path
else
flash[:error] = @custom_style.errors.full_messages

@ -67,7 +67,7 @@ class EnumerationsController < ApplicationController
enum_params = permitted_params.enumerations
type = permitted_params.enumeration_type
@enumeration.type = enumeration_class(type).try(:name) || @enumeration.type
if @enumeration.update_attributes enum_params
if @enumeration.update enum_params
flash[:notice] = l(:notice_successful_update)
redirect_to enumerations_path(type: @enumeration.type)
else

@ -106,7 +106,7 @@ class ForumsController < ApplicationController
def edit; end
def update
if @forum.update_attributes(permitted_params.forum)
if @forum.update(permitted_params.forum)
flash[:notice] = l(:notice_successful_update)
redirect_to_settings_in_projects
else
@ -115,7 +115,7 @@ class ForumsController < ApplicationController
end
def move
if @forum.update_attributes(permitted_params.forum_move)
if @forum.update(permitted_params.forum_move)
flash[:notice] = t(:notice_successful_update)
else
flash.now[:error] = t('forum_could_not_be_saved')

@ -97,7 +97,7 @@ class GroupsController < ApplicationController
@group = Group.includes(:users).find(params[:id])
respond_to do |format|
if @group.update_attributes(permitted_params.group)
if @group.update(permitted_params.group)
flash[:notice] = l(:notice_successful_update)
format.html do redirect_to(groups_path) end
format.xml do head :ok end

@ -46,7 +46,7 @@ class HighlightingController < ApplicationController
private
def determine_freshness
@max_updated_at = helpers.highlight_css_updated_at || Time.now.iso8601
@max_updated_at = helpers.highlight_css_updated_at.to_s || Time.now.iso8601
@highlight_version_tag = helpers.highlight_css_version_tag(@max_updated_at)
end
end

@ -246,14 +246,10 @@ class ProjectsController < ApplicationController
@query = ParamsToQueryService.new(Project, current_user).call(params)
# Set default filter on status no filter is provided.
if !params[:filters]
@query.where('status', '=', Project::STATUS_ACTIVE.to_s)
end
@query.where('status', '=', Project::STATUS_ACTIVE.to_s) unless params[:filters]
# Order lft if no order is provided.
if !params[:sortBy]
@query.order(lft: :asc)
end
@query.order(lft: :asc) unless params[:sortBy]
@query
end
@ -284,15 +280,11 @@ class ProjectsController < ApplicationController
end
def load_projects(query)
projects = query
.results
.with_required_storage
.with_latest_activity
.includes(:custom_values, :enabled_modules)
.page(page_param)
.per_page(per_page_param)
filter_projects_by_permission projects
filter_projects_by_permission(query.results)
.with_required_storage
.with_latest_activity
.includes(:custom_values, :enabled_modules)
.paginate(page: page_param, per_page: per_page_param)
end
def update_demo_project_settings(project, value)

@ -66,7 +66,7 @@ class StatusesController < ApplicationController
verify method: :patch, only: :update, render: { nothing: true, status: :method_not_allowed }
def update
@status = Status.find(params[:id])
if @status.update_attributes(permitted_params.status)
if @status.update(permitted_params.status)
flash[:notice] = l(:notice_successful_update)
redirect_to action: 'index'
else

@ -101,7 +101,7 @@ class TypesController < ApplicationController
def move
@type = ::Type.find(params[:id])
if @type.update_attributes(permitted_params.type_move)
if @type.update(permitted_params.type_move)
flash[:notice] = l(:notice_successful_update)
else
flash.now[:error] = t('type_could_not_be_saved')

@ -224,7 +224,7 @@ class WikiController < ApplicationController
existing_identifier: item.name)
redirect_to_show
elsif @page.update_attributes(attributes)
elsif @page.update(attributes)
flash[:notice] = t(:notice_successful_update)
redirect_to_show
end

@ -32,17 +32,16 @@ class AuthSource < ActiveRecord::Base
has_many :users
validates_presence_of :name
validates_uniqueness_of :name
validates_length_of :name, maximum: 60
validates :name,
uniqueness: { case_sensitive: false },
length: { maximum: 60 }
def self.unique_attribute
:name
end
prepend ::Mixins::UniqueFinder
def authenticate(_login, _password)
end
def authenticate(_login, _password); end
def find_user(_login)
raise "subclass repsonsiblity"

@ -32,9 +32,9 @@ class Category < ActiveRecord::Base
belongs_to :assigned_to, class_name: 'Principal', foreign_key: 'assigned_to_id'
has_many :work_packages, foreign_key: 'category_id', dependent: :nullify
validates_presence_of :name
validates_uniqueness_of :name, scope: [:project_id]
validates_length_of :name, maximum: 255
validates :name,
uniqueness: { scope: [:project_id], case_sensitive: true },
length: { maximum: 255 }
# validates that assignee is member of the issue category's project
validates_each :assigned_to_id do |record, attr, value|

@ -30,8 +30,9 @@
class EnabledModule < ActiveRecord::Base
belongs_to :project
validates_presence_of :name
validates_uniqueness_of :name, scope: :project_id
validates :name,
presence: true,
uniqueness: { scope: :project_id, case_sensitive: true }
after_create :module_enabled

@ -60,7 +60,7 @@ class Journal < ActiveRecord::Base
if attributes.is_a? Hash and attributes.values.first.is_a? Array
attributes.each { |k, v| attributes[k] = v[1] }
end
data.update_attributes attributes
data.update attributes
end
# In conjunction with the included Comparable module, allows comparison of journal records

@ -35,11 +35,13 @@ class MenuItem < ActiveRecord::Base
serialize :options, Hash
validates_presence_of :title
validates_uniqueness_of :title, scope: [:navigatable_id, :type]
validates :title,
presence: true,
uniqueness: { scope: %i[navigatable_id type], case_sensitive: true }
validates_presence_of :name
validates_uniqueness_of :name, scope: [:navigatable_id, :parent_id]
validates :name,
presence: true,
uniqueness: { scope: %i[navigatable_id parent_id], case_sensitive: true }
def setting
if new_record?

@ -154,21 +154,25 @@ class Project < ActiveRecord::Base
author: nil,
datetime: :created_on
validates_presence_of :name, :identifier
validates :name,
presence: true,
length: { maximum: 255 }
# TODO: we temporarily disable this validation because it leads to failed tests
# it implicitly assumes a db:seed-created standard type to be present and currently
# neither development nor deployment setups are prepared for this
# validates_presence_of :types
validates_uniqueness_of :identifier
validates :identifier,
presence: true,
uniqueness: { case_sensitive: true },
length: { maximum: IDENTIFIER_MAX_LENGTH },
exclusion: RESERVED_IDENTIFIERS
validates_associated :repository, :wiki
validates_length_of :name, maximum: 255
validates_length_of :identifier, in: 1..IDENTIFIER_MAX_LENGTH
# starts with lower-case letter, a-z, 0-9, dashes and underscores afterwards
validates :identifier,
format: { with: /\A[a-z][a-z0-9\-_]*\z/ },
if: ->(p) { p.identifier_changed? }
# reserved words
validates_exclusion_of :identifier, in: RESERVED_IDENTIFIERS
friendly_id :identifier, use: :finders
@ -176,7 +180,7 @@ class Project < ActiveRecord::Base
where(["#{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name=?)", mod.to_s])
}
scope :public_projects, -> { where(is_public: true) }
scope :visible, ->(user = User.current) { Project.visible_by(user) }
scope :visible, ->(user = User.current) { merge(Project.visible_by(user)) }
scope :newest, -> { order(created_on: :desc) }
def visible?(user = User.current)

@ -43,7 +43,7 @@ class Queries::WorkPackages::Columns::PropertyColumn < Queries::WorkPackages::Co
project: {
association: 'project',
sortable: "name",
groupable: true
groupable: 'project_id'
},
subject: {
sortable: "#{WorkPackage.table_name}.subject"
@ -51,7 +51,7 @@ class Queries::WorkPackages::Columns::PropertyColumn < Queries::WorkPackages::Co
type: {
association: 'type',
sortable: "position",
groupable: true
groupable: 'type_id'
},
parent: {
association: 'ancestors_relations',
@ -62,35 +62,35 @@ class Queries::WorkPackages::Columns::PropertyColumn < Queries::WorkPackages::Co
association: 'status',
sortable: "position",
highlightable: true,
groupable: true
groupable: 'status_id'
},
priority: {
association: 'priority',
sortable: "position",
default_order: 'desc',
highlightable: true,
groupable: true
groupable: 'priority_id'
},
author: {
association: 'author',
sortable: ["lastname",
"firstname",
"id"],
groupable: true
groupable: 'author_id'
},
assigned_to: {
association: 'assigned_to',
sortable: ["lastname",
"firstname",
"id"],
groupable: true
groupable: 'assigned_to_id'
},
responsible: {
association: 'responsible',
sortable: ["lastname",
"firstname",
"id"],
groupable: true
groupable: 'responsible_id'
},
updated_at: {
sortable: "#{WorkPackage.table_name}.updated_at",
@ -99,13 +99,13 @@ class Queries::WorkPackages::Columns::PropertyColumn < Queries::WorkPackages::Co
category: {
association: 'category',
sortable: "name",
groupable: true
groupable: 'category_id'
},
fixed_version: {
association: 'fixed_version',
sortable: ["name"],
default_order: 'desc',
groupable: true
groupable: 'fixed_version_id'
},
start_date: {
# Put empty start_dates in the far future rather than in the far past

@ -188,6 +188,7 @@ class Query < ActiveRecord::Base
def add_short_filter(field, expression)
return unless expression
parms = expression.scan(/\A(o|c|!\*|!|\*)?(.*)\z/).first
add_filter field, (parms[0] || '='), [parms[1] || '']
end
@ -372,9 +373,8 @@ class Query < ActiveRecord::Base
end
# Returns the result set
# Valid options are :order, :include, :conditions
def results(options = {})
Results.new(self, options)
def results
Results.new(self)
end
# Returns the journals

@ -1,4 +1,5 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
@ -32,7 +33,7 @@ module ::Query::Grouping
def work_package_count_by_group
@work_package_count_by_group ||= begin
if query.grouped?
r = groups_grouped_by_column
r = group_counts_by_group
transform_group_keys(r)
end
@ -45,33 +46,58 @@ module ::Query::Grouping
work_package_count_by_group[group]
end
def groups_grouped_by_column
# Rails will raise an (unexpected) RecordNotFound if there's only a nil group value
WorkPackage
.group(query.group_by_statement)
private
def group_counts_by_group
work_packages_with_includes_for_count
.group(group_by_for_count)
.visible
.includes(all_includes)
.joins(all_filter_joins)
.references(:statuses, :projects)
.where(query.statement)
.count
rescue ActiveRecord::RecordNotFound
{ nil => work_package_count }
.order(order_for_count)
.pluck(pluck_for_count)
.to_h
end
def work_packages_with_includes_for_count
WorkPackage
.includes(all_includes)
.joins(all_filter_joins)
end
def group_by_for_count
Array(query.group_by_statement).map { |statement| Arel.sql(statement) } +
[Arel.sql(group_by_sort(false))]
end
def pluck_for_count
Array(query.group_by_statement).map { |statement| Arel.sql(statement) } +
[Arel.sql('COUNT(DISTINCT "work_packages"."id")')]
end
def order_for_count
Arel.sql(group_by_sort)
end
def transform_group_keys(groups)
column = query.group_by_column
if query.group_by_column.is_a?(Queries::WorkPackages::Columns::CustomFieldColumn)
transform_custom_field_keys(groups)
else
transform_property_keys(groups)
end
end
if column.is_a?(Queries::WorkPackages::Columns::CustomFieldColumn) && column.custom_field.list?
transform_list_group_by_keys(column.custom_field, groups)
elsif column.is_a?(Queries::WorkPackages::Columns::CustomFieldColumn)
transform_custom_field_keys(column.custom_field, groups)
def transform_custom_field_keys(groups)
custom_field = query.group_by_column.custom_field
if custom_field.list?
transform_list_custom_field_keys(custom_field, groups)
else
groups
transform_single_custom_field_keys(custom_field, groups)
end
end
def transform_list_group_by_keys(custom_field, groups)
def transform_list_custom_field_keys(custom_field, groups)
options = custom_options_for_keys(custom_field, groups)
groups.transform_keys do |key|
@ -96,25 +122,52 @@ module ::Query::Grouping
custom_field.custom_options.find(keys.flatten.uniq).group_by { |o| o.id.to_s }
end
def transform_custom_field_keys(custom_field, groups)
def transform_single_custom_field_keys(custom_field, groups)
groups.transform_keys { |key| custom_field.cast_value(key) }
end
def transform_property_keys(groups)
association = WorkPackage.reflect_on_all_associations.detect { |a| a.name == query.group_by_column.name.to_sym }
if association
transform_association_property_keys(association, groups)
else
groups
end
end
def transform_association_property_keys(association, groups)
ar_keys = association.class_name.constantize.find(groups.keys)
groups.map do |key, value|
[ar_keys.detect { |ar_key| ar_key.id == key }, value]
end.to_h
end
# Returns the SQL sort order that should be prepended for grouping
def group_by_sort_order
def group_by_sort(order = true)
if query.grouped? && (column = query.group_by_column)
aliases = include_aliases
Array(column.sortable).map do |s|
aliased_group_by_sort_order(s, order_for_group_by(column), aliases[column.name])
end.join(',')
direction = order ? order_for_group_by(column) : nil
aliased_group_by_sort_order(aliases[column.name], s, direction)
end.join(', ')
end
end
def aliased_group_by_sort_order(sortable, order, alias_name)
if alias_name
"#{alias_name}.#{sortable} #{order}"
def aliased_group_by_sort_order(alias_name, sortable, order = nil)
column = if alias_name
"#{alias_name}.#{sortable}"
else
sortable
end
if order
column + " #{order}"
else
"#{sortable} #{order}"
column
end
end

@ -36,12 +36,9 @@ class ::Query::Results
include ::Query::Sums
include Redmine::I18n
attr_accessor :options,
:query
attr_accessor :query
# Valid options are :order, :include, :conditions
def initialize(query, options = {})
self.options = options
def initialize(query)
self.query = query
end
@ -60,7 +57,6 @@ class ::Query::Results
def work_packages
work_package_scope
.where(query.statement)
.where(options[:conditions])
.includes(all_includes)
.joins(all_joins)
.order(order_option)
@ -78,7 +74,6 @@ class ::Query::Results
def versions
scope = Version
.visible
.where(options[:conditions])
if query.project
scope.where(query.project_limiting_filter.where)
@ -88,7 +83,7 @@ class ::Query::Results
end
def order_option
order_option = [group_by_sort_order].reject(&:blank?).join(', ')
order_option = [group_by_sort].reject(&:blank?).join(', ')
if order_option.blank?
nil
@ -107,8 +102,7 @@ class ::Query::Results
def all_includes
(%i(status project) +
includes_for_columns(include_columns) +
(options[:include] || [])).uniq
includes_for_columns(include_columns)).uniq
end
def all_joins

@ -58,9 +58,10 @@ class Role < ActiveRecord::Base
acts_as_list
validates_presence_of :name
validates_uniqueness_of :name
validates_length_of :name, maximum: 30
validates :name,
presence: true,
length: { maximum: 30 },
uniqueness: { case_sensitive: true }
def self.givable
where(builtin: NON_BUILTIN)

@ -40,9 +40,11 @@ class Status < ActiveRecord::Base
before_destroy :delete_workflows
validates_presence_of :name
validates_uniqueness_of :name
validates_length_of :name, maximum: 30
validates :name,
presence: true,
uniqueness: { case_sensitive: false },
length: { maximum: 30 }
validates_inclusion_of :default_done_ratio, in: 0..100, allow_nil: true
after_save :unmark_old_default_value, if: :is_default?

@ -51,16 +51,16 @@ class ::Type < ActiveRecord::Base
join_table: "#{table_name_prefix}custom_fields_types#{table_name_suffix}",
association_foreign_key: 'custom_field_id'
belongs_to :color, class_name: 'Color',
foreign_key: 'color_id'
belongs_to :color,
class_name: 'Color',
foreign_key: 'color_id'
acts_as_list
validates_presence_of :name
validates_uniqueness_of :name
validates_length_of :name,
maximum: 255,
unless: lambda { |e| e.name.blank? }
validates :name,
presence: true,
uniqueness: { case_sensitive: true },
length: { maximum: 255 }
validates_inclusion_of :is_default, :is_milestone, in: [true, false]

@ -39,9 +39,10 @@ class Version < ActiveRecord::Base
VERSION_STATUSES = %w(open locked closed).freeze
VERSION_SHARINGS = %w(none descendants hierarchy tree system).freeze
validates_presence_of :name
validates_uniqueness_of :name, scope: [:project_id]
validates_length_of :name, maximum: 60
validates :name,
presence: true,
uniqueness: { scope: [:project_id], case_sensitive: true }
validates_format_of :effective_date, with: /\A\d{4}-\d{2}-\d{2}\z/, message: :not_a_date, allow_nil: true
validates_format_of :start_date, with: /\A\d{4}-\d{2}-\d{2}\z/, message: :not_a_date, allow_nil: true
validates_inclusion_of :status, in: VERSION_STATUSES

@ -35,7 +35,7 @@ module BasicData
end
builtin_roles.each do |attributes|
Role.find_by!(name: attributes[:name]).update_attributes(attributes)
Role.find_by!(name: attributes[:name]).update(attributes)
end
end
end

@ -34,7 +34,8 @@ class Authorization::AbstractQuery
def self.query(*args)
arel = transformed_query(*args)
model.joins(joins(arel))
model.unscoped
.joins(joins(arel))
.where(wheres(arel))
.distinct
end

@ -37,4 +37,4 @@ See docs/COPYRIGHT.rdoc for more details.
<% @page_header_title = l(:label_administration) %>
<%= render file: "layouts/base", locals: { menu_name: :admin_menu } %>
<%= render template: "layouts/base", locals: { menu_name: :admin_menu } %>

@ -27,4 +27,4 @@ See docs/COPYRIGHT.rdoc for more details.
++#%>
<%= render file: "layouts/base", locals: { menu_name: :my_menu } %>
<%= render template: "layouts/base", locals: { menu_name: :my_menu } %>

@ -27,4 +27,4 @@ See docs/COPYRIGHT.rdoc for more details.
++#%>
<%= render file: "layouts/base", locals: { menu_name: nil, current_menu_item: nil } %>
<%= render template: "layouts/base", locals: { menu_name: nil, current_menu_item: nil } %>

@ -42,7 +42,7 @@ class Scm::StorageUpdaterJob < ApplicationJob
repository = Repository.find @id
bytes = repository.scm.count_repository!
repository.update_attributes!(
repository.update!(
required_storage_bytes: bytes,
storage_updated_at: Time.now,
)

@ -1,9 +0,0 @@
coverage:
ignore:
- spec/factories/.*
- vendor/bundle/.*
status:
patch: false
project:
default: {}
comment: off

@ -173,6 +173,10 @@ module OpenProject
# Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header.
Rails.application.config.active_support.use_sha1_digests = true
# This option is not backwards compatible with earlier Rails versions.
# It's best enabled when your entire app is migrated and stable on 6.0.
Rails.application.config.action_dispatch.use_cookies_with_metadata = true
# Make `form_with` generate id attributes for any generated HTML tags.
# Rails.application.config.action_view.form_with_generates_ids = true
@ -200,6 +204,9 @@ module OpenProject
config.action_controller.asset_host = OpenProject::Configuration::AssetHost.value
# Return false instead of self when enqueuing is aborted from a callback.
# Rails.application.config.active_job.return_false_on_aborted_enqueue = true
config.log_level = OpenProject::Configuration['log_level'].to_sym
def self.root_url

@ -0,0 +1,10 @@
development:
adapter: async
test:
adapter: test
production:
adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: open_project_production

@ -48,7 +48,7 @@ Given /^the [pP]roject(?: "([^\"]+?)")? uses the following types:$/ do |project,
type
}
project.update_attributes type_ids: types.map(&:id).map(&:to_s)
project.update type_ids: types.map(&:id).map(&:to_s)
end
Then(/^I should see the following fields:$/) do |table|

@ -34,11 +34,6 @@
# instead of editing this one. Cucumber will automatically load all features/**/*.rb
# files.
if ENV['COVERAGE']
require 'simplecov'
SimpleCov.start 'rails'
end
require 'cucumber/rails'
require 'cucumber/rspec/doubles'
require 'capybara-screenshot/cucumber'

@ -1,4 +1,5 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)

@ -31,9 +31,13 @@
module OpenProject::TextFormatting
module Filters
class SanitizationFilter < HTML::Pipeline::SanitizationFilter
WHITELIST[:elements] << 'macro'
# Whitelist class and data-* attributes on all macros
WHITELIST[:attributes].merge!('macro' => ['class', :data])
def context
super.merge(whitelist: WHITELIST.merge(
elements: WHITELIST[:elements] + ['macro'],
# Whitelist class and data-* attributes on all macros
attributes: WHITELIST[:attributes].merge('macro' => ['class', :data])
))
end
end
end
end

@ -29,11 +29,12 @@
module OpenProject::TextFormatting::Formats
class BaseFormatter
attr_reader :options, :project
attr_reader :context,
:pipeline
def initialize(options)
@options = options
@project = options[:project]
def initialize(context)
@context = context
@pipeline = HTML::Pipeline.new(located_filters, context)
end
def to_html(text)

@ -31,14 +31,6 @@ require 'task_list/filter'
module OpenProject::TextFormatting::Formats::Markdown
class Formatter < OpenProject::TextFormatting::Formats::BaseFormatter
attr_reader :context,
:pipeline
def initialize(context)
@context = context
@pipeline = ::HTML::Pipeline.new(located_filters, context)
end
def to_html(text)
result = pipeline.call(text, context)
output = result[:output].to_s

@ -31,14 +31,6 @@
module OpenProject::TextFormatting::Formats
module Plain
class Formatter < OpenProject::TextFormatting::Formats::BaseFormatter
attr_reader :context,
:pipeline
def initialize(context)
@context = context
@pipeline = HTML::Pipeline.new(located_filters, context)
end
def to_html(text)
pipeline.to_html(text, context).html_safe
end

@ -33,7 +33,7 @@ require 'open3'
module OpenProject
module VERSION #:nodoc:
MAJOR = 10
MINOR = 0
MINOR = 1
PATCH = 0
TINY = PATCH # Redmine compat

@ -109,14 +109,18 @@ module Redmine
# because while they have the right to be added as watchers having
# them pop up in every project would be weird.
def possible_watcher_users
users = User
.active_or_registered
if project.is_public?
users.allowed(self.class.acts_as_watchable_permission, project)
else
users.allowed_members(self.class.acts_as_watchable_permission, project)
end
# In rails 6, for reasons I did not look into, a different sql is produced
# when issuing
# User.active_or_registered.allowed_members(self.class.acts_as_watchable_permission, project)
# compared to
# User.allowed_members(self.class.acts_as_watchable_permission, project).active_or_registered
scope = if project.is_public?
User.allowed(self.class.acts_as_watchable_permission, project)
else
User.allowed_members(self.class.acts_as_watchable_permission, project)
end
scope.active_or_registered
end
# Returns an array of users that are proposed as watchers

@ -26,7 +26,7 @@ module OpenProject
# Don't allow unsetting admin if user is already admin
attributes.delete(:admin) if user.admin?
user.update_attributes attributes
user.update attributes
end
end

@ -60,7 +60,7 @@ class RbApplicationController < ApplicationController
settings = Setting.plugin_openproject_backlogs
if settings['story_types'].blank? || settings['task_type'].blank?
respond_to do |format|
format.html { render file: 'shared/not_configured' }
format.html { render template: 'shared/not_configured' }
end
end
end

@ -39,7 +39,7 @@
# RbTaskboardsController
class RbSprintsController < RbApplicationController
def update
result = @sprint.update_attributes(params.permit(:name,
result = @sprint.update(params.permit(:name,
:start_date,
:effective_date))
status = (result ? 200 : 400)

@ -399,7 +399,7 @@ module OpenProject::Bcf::BcfXml
end
def update_journal_attributes(bcf_comment, comment_data)
bcf_comment.journal.update_attributes(notes: comment_data[:comment],
bcf_comment.journal.update(notes: comment_data[:comment],
created_at: comment_data[:modified_date])
bcf_comment.journal.save
end

@ -14,6 +14,5 @@ Gem::Specification.new do |s|
s.test_files = Dir["spec/**/*"]
s.add_dependency 'activerecord-import'
s.add_dependency 'rails', '~> 5'
s.add_dependency 'rubyzip', '~> 1.2'
end

@ -71,7 +71,7 @@ describe DocumentsController do
}
before do
document.update_attributes(description: long_description)
document.update(description: long_description)
get :index, params: { project_id: project.identifier }
end

@ -54,7 +54,7 @@ module API
post &::API::V3::Utilities::Endpoints::Create.new(model: ::Grids::Grid).mount
mount CreateFormAPI
mount ::API::V3::Grids::CreateFormAPI
mount ::API::V3::Grids::Schemas::GridSchemaAPI
route_param :id, type: Integer, desc: 'Grid ID' do
@ -105,7 +105,7 @@ module API
.mount
delete &::API::V3::Utilities::Endpoints::Delete.new(model: ::Grids::Grid).mount
mount UpdateFormAPI
mount ::API::V3::Grids::UpdateFormAPI
end
end
end

@ -58,7 +58,7 @@ class ExportCardConfigurationsController < ApplicationController
if cannot_update_default
flash[:error] = l(:error_can_not_change_name_of_default_configuration)
render "edit"
elsif @config.update_attributes(export_card_configurations_params)
elsif @config.update(export_card_configurations_params)
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'index'
else

@ -108,12 +108,12 @@ class ExportCardConfiguration < ActiveRecord::Base
end
def activate
self.update_attributes!({active: true})
self.update!({active: true})
end
def deactivate
if !self.is_default?
self.update_attributes!({active: false})
self.update!({active: false})
else
false
end

@ -15,7 +15,7 @@ Gem::Specification.new do |s|
s.add_dependency "reporting_engine"
s.add_dependency "openproject-costs"
s.add_dependency 'jquery-tablesorter', '~> 1.25.5'
s.add_dependency 'jquery-tablesorter', '~> 1.27.0'
s.add_development_dependency "factory_girl_rails", "~> 4.0"
end

@ -14,7 +14,6 @@
require File.expand_path('../../spec_helper', __FILE__)
describe OpenProject::Webhooks::Hook do
describe '#relative_url' do
let(:hook) { OpenProject::Webhooks::Hook.new('myhook')}

@ -107,7 +107,7 @@ shared_examples_for 'project contract' do
let(:project_identifier) { nil }
it 'is invalid' do
expect_valid(false, identifier: %i(blank too_short))
expect_valid(false, identifier: %i(blank))
end
end

@ -119,7 +119,7 @@ describe CustomStylesController, type: :controller do
with_enterprise_token(:define_custom_style)
expect(CustomStyle).to receive(:current).and_return(custom_style)
expect(custom_style).to receive(:update_attributes).and_return(valid)
expect(custom_style).to receive(:update).and_return(valid)
post :update, params: params
end

@ -241,7 +241,7 @@ describe WikiController, type: :controller do
@anon = User.anonymous.nil? ? FactoryBot.create(:anonymous) : User.anonymous
Role.anonymous.update_attributes name: I18n.t(:default_role_anonymous),
Role.anonymous.update name: I18n.t(:default_role_anonymous),
permissions: [:view_wiki_pages]
allow(User).to receive(:current).and_return @user

@ -38,14 +38,14 @@ FactoryBot.define do
name { 'Non member' }
builtin { Role::BUILTIN_NON_MEMBER }
assignable { false }
initialize_with { Role.find_or_create_by(name: name) }
initialize_with { Role.where(name: name).first_or_initialize }
end
factory :anonymous_role do
name { 'Anonymous' }
builtin { Role::BUILTIN_ANONYMOUS }
assignable { false }
initialize_with { Role.find_or_create_by(name: name) }
initialize_with { Role.where(name: name).first_or_initialize }
end
factory :existing_role do

@ -52,7 +52,7 @@ describe 'Projects#destroy',
it 'can destroy the project' do
# Confirm the deletion
danger_zone.confirm_with(project.identifier)
expect(danger_zone.disabled?).to be false
expect(danger_zone).not_to be_disabled
danger_zone.danger_button.click
expect(page).to have_selector '.flash.notice', text: I18n.t('projects.delete.scheduled')

@ -121,7 +121,7 @@ describe 'Projects index page',
feature 'for admins' do
before do
project.update_attributes(created_on: 7.days.ago)
project.update(created_on: 7.days.ago)
news
end
@ -538,10 +538,10 @@ describe 'Projects index page',
cf_filter = page.find("li[filter-name='cf_#{list_custom_field.id}']")
within(cf_filter) do
# Initial filter is a 'single select'
expect(cf_filter.find(:select, 'value')[:multiple]).to be_falsey
expect(cf_filter.find(:select, 'value')).not_to be_multiple
click_on 'Toggle multiselect'
# switching to multiselect keeps the current selection
expect(cf_filter.find(:select, 'value')[:multiple]).to be_truthy
expect(cf_filter.find(:select, 'value')).to be_multiple
expect(cf_filter).to have_select('value', selected: list_custom_field.possible_values[2].value)
select list_custom_field.possible_values[3].value, from: 'value'
@ -552,7 +552,7 @@ describe 'Projects index page',
cf_filter = page.find("li[filter-name='cf_#{list_custom_field.id}']")
within(cf_filter) do
# Query has two values for that filter, so it shoud show a 'multi select'.
expect(cf_filter.find(:select, 'value')[:multiple]).to be_truthy
expect(cf_filter.find(:select, 'value')).to be_multiple
expect(cf_filter)
.to have_select('value',
selected: [list_custom_field.possible_values[2].value,
@ -563,7 +563,7 @@ describe 'Projects index page',
unselect list_custom_field.possible_values[2].value, from: 'value'
click_on 'Toggle multiselect'
expect(cf_filter.find(:select, 'value')[:multiple]).to be_falsey
expect(cf_filter.find(:select, 'value')).not_to be_multiple
expect(cf_filter).to have_select('value', selected: list_custom_field.possible_values[1].value)
expect(cf_filter).to_not have_select('value', selected: list_custom_field.possible_values[3].value)
end
@ -573,7 +573,7 @@ describe 'Projects index page',
cf_filter = page.find("li[filter-name='cf_#{list_custom_field.id}']")
within(cf_filter) do
# Query has one value for that filter, so it should show a 'single select'.
expect(cf_filter.find(:select, 'value')[:multiple]).to be_falsey
expect(cf_filter.find(:select, 'value')).not_to be_multiple
end
# CF date filter work (at least for one operator)
@ -631,7 +631,7 @@ describe 'Projects index page',
# Remove public projects from the default list for these scenarios.
public_project.update_attribute :status, Project::STATUS_ARCHIVED
project.update_attributes(created_on: 7.days.ago)
project.update(created_on: 7.days.ago)
news
end

@ -108,7 +108,7 @@ describe 'Create repository', type: :feature, js: true, selenium: true do
it 'should display a collapsed type' do
expect(selector).not_to be_nil
expect(selector[:selected]).to be_falsey
expect(selector[:disabled]).to be_falsey
expect(selector).not_to be_disabled
content = find("##{vendor}-#{type}", visible: false)
expect(content).not_to be_nil
@ -124,7 +124,7 @@ describe 'Create repository', type: :feature, js: true, selenium: true do
find("input[name='scm_type'][value='#{type}']").set(true)
content = find("#attributes-group--content-#{type}")
expect(content).not_to be_nil
expect(content[:hidden]).to be_falsey
expect(content[:hidden]).to eql 'false'
content = find("##{vendor}-#{type}", visible: false)
expect(content).not_to be_nil
expect(content[:style]).not_to match("display: none")
@ -132,7 +132,7 @@ describe 'Create repository', type: :feature, js: true, selenium: true do
find('input[type="radio"][value="managed"]').set(true)
content = find('#attributes-group--content-managed')
expect(content).not_to be_nil
expect(content[:hidden]).to be_falsey
expect(content[:hidden]).to eql 'false'
content = find("##{vendor}-managed", visible: false)
expect(content).not_to be_nil
expect(content[:style]).not_to match("display: none")

@ -65,6 +65,6 @@ class DangerZone
##
def disabled?
!!danger_button[:disabled]
danger_button.disabled?
end
end

@ -79,7 +79,7 @@ describe 'index users', type: :feature do
index_page.expect_listed(active_user)
# temporarily block user
active_user.update_attributes(failed_login_count: 6,
active_user.update(failed_login_count: 6,
last_failed_login_on: 9.minutes.ago)
index_page.clear_filters
index_page.expect_listed(admin, active_user, registered_user, invited_user)
@ -92,7 +92,7 @@ describe 'index users', type: :feature do
# temporarily block user and lock permanently
active_user.reload
active_user.update_attributes(failed_login_count: 6,
active_user.update(failed_login_count: 6,
last_failed_login_on: 9.minutes.ago)
index_page.clear_filters

@ -35,10 +35,10 @@ describe 'my',
let(:user_password) { 'bob' * 4 }
let(:user) do
FactoryBot.create(:user,
mail: 'old@mail.com',
login: 'bob',
password: user_password,
password_confirmation: user_password)
mail: 'old@mail.com',
login: 'bob',
password: user_password,
password_confirmation: user_password)
end
##
@ -98,11 +98,11 @@ describe 'my',
end
context 'as admin' do
let(:user) {
let(:user) do
FactoryBot.create :admin,
password: user_password,
password_confirmation: user_password
}
password: user_password,
password_confirmation: user_password
end
it 'requires the password' do
dialog.confirm_flow_with(user_password)

@ -1,15 +1,14 @@
require 'spec_helper'
describe 'Milestones full screen v iew', js: true do
let(:type) { FactoryBot.create :type, is_milestone: true }
let(:project) { FactoryBot.create(:project, types: [type]) }
let!(:work_package) {
let!(:work_package) do
FactoryBot.create(:work_package,
project: project,
type: type,
subject: 'Foobar')
}
end
let(:wp_page) { ::Pages::FullWorkPackage.new(work_package, project) }
let(:button) { find('.add-work-package', wait: 5) }
@ -29,7 +28,7 @@ describe 'Milestones full screen v iew', js: true do
end
it 'shows the button as enabled' do
expect(button['disabled']).to be_falsey
expect(button).not_to be_disabled
button.click
expect(page).to have_selector('.menu-item', text: type.name.upcase)

@ -50,7 +50,7 @@ describe 'edit work package', js: true do
created_at: 5.days.ago.to_date.to_s(:db))
note_journal = work_package.journals.last
note_journal.update_attributes(created_at: 5.days.ago.to_date.to_s)
note_journal.update(created_at: 5.days.ago.to_date.to_s)
work_package
end

@ -5,10 +5,10 @@ require 'support/work_packages/work_package_field'
describe 'Activity tab', js: true, selenium: true do
def alter_work_package_at(work_package, attributes:, at:, user: User.current)
work_package.update_attributes(attributes.merge(updated_at: at))
work_package.update(attributes.merge(updated_at: at))
note_journal = work_package.journals.last
note_journal.update_attributes(created_at: at, user: attributes[:user])
note_journal.update(created_at: at, user: attributes[:user])
end
let(:project) { FactoryBot.create :project_with_types, is_public: true }
@ -20,7 +20,7 @@ describe 'Activity tab', js: true, selenium: true do
journal_notes: initial_comment)
note_journal = work_package.journals.last
note_journal.update_attributes(created_at: 5.days.ago.to_date.to_s)
note_journal.update(created_at: 5.days.ago.to_date.to_s)
work_package
end

@ -5,10 +5,10 @@ require 'support/work_packages/work_package_field'
describe 'Activity tab', js: true, selenium: true do
def alter_work_package_at(work_package, attributes:, at:, user: User.current)
work_package.update_attributes(attributes.merge(updated_at: at))
work_package.update(attributes.merge(updated_at: at))
note_journal = work_package.journals.last
note_journal.update_attributes(created_at: at, user: attributes[:user])
note_journal.update(created_at: at, user: attributes[:user])
end
let(:project) { FactoryBot.create :project_with_types, is_public: true }
@ -20,7 +20,7 @@ describe 'Activity tab', js: true, selenium: true do
journal_notes: initial_comment)
note_journal = work_package.journals.last
note_journal.update_attributes(created_at: 5.days.ago.to_date.to_s)
note_journal.update(created_at: 5.days.ago.to_date.to_s)
work_package
end

@ -55,7 +55,7 @@ describe 'Work package transitive status workflows', js: true do
created_at: 5.days.ago.to_date.to_s(:db)
note_journal = work_package.journals.last
note_journal.update_attributes(created_at: 5.days.ago.to_date.to_s)
note_journal.update(created_at: 5.days.ago.to_date.to_s)
work_package
}

@ -415,7 +415,9 @@ describe OpenProject::Configuration do
end
describe '.configure_cache' do
let(:application_config) { Rails::Application::Configuration.new }
let(:application_config) do
Rails::Application::Configuration.new Rails.root
end
after do
# reload configuration to isolate specs

@ -18,7 +18,7 @@ describe ApplicationRecord, type: :model do
def expect_matched_date(postgres_time, rails_time)
# Rails uses timestamp without timezone for timestamp columns
postgres_utc_iso8601 = Time.zone.parse(postgres_time).iso8601
postgres_utc_iso8601 = Time.zone.parse(postgres_time.to_s).iso8601
rails_utc_iso8601 = rails_time.iso8601
expect(postgres_utc_iso8601).to eq(rails_utc_iso8601)

@ -47,7 +47,7 @@ describe Project::Storage, type: :model do
FactoryBot.create(:attachment, filesize: 10000, container: wikipage)
repo = FactoryBot.create(:repository_git, project: project2)
repo.update_attributes(required_storage_bytes: 1234)
repo.update(required_storage_bytes: 1234)
end
describe '#with_required_storage' do
@ -80,7 +80,7 @@ describe Project::Storage, type: :model do
context 'with a project with all modules' do
let(:repository1) { FactoryBot.create(:repository_git, project: project1) }
before do
repository1.update_attributes(required_storage_bytes: 543211234)
repository1.update(required_storage_bytes: 543211234)
end
it 'counts all projects correctly' do

@ -28,21 +28,13 @@
require 'spec_helper'
describe ::Query::Results, type: :model do
describe ::Query::Results, type: :model, with_mail: false do
let(:query) do
FactoryBot.build :query,
show_hierarchies: false
end
let(:query_results) do
::Query::Results.new query,
include: %i(
assigned_to
type
priority
category
fixed_version
),
order: 'work_packages.root_id DESC, work_packages.lft ASC'
::Query::Results.new query
end
let(:project_1) { FactoryBot.create :project }
let(:role_pm) do
@ -77,10 +69,27 @@ describe ::Query::Results, type: :model do
let(:query) do
FactoryBot.build :query,
show_hierarchies: false,
group_by: group_by
group_by: group_by,
project: project_1
end
let(:type_1) do
FactoryBot.create(:type)
end
let(:type_2) do
FactoryBot.create(:type)
end
let(:work_package1) do
FactoryBot.create(:work_package,
type: type_1,
project: project_1)
end
let(:work_package2) do
FactoryBot.create(:work_package,
type: type_2,
project: project_1)
end
context 'when grouping by responsible' do
context 'grouping by responsible' do
let(:group_by) { 'responsible' }
it 'should produce a valid SQL statement' do
@ -88,7 +97,7 @@ describe ::Query::Results, type: :model do
end
end
context 'when grouping and filtering by text' do
context 'grouping and filtering by text' do
let(:group_by) { 'responsible' }
before do
@ -99,6 +108,175 @@ describe ::Query::Results, type: :model do
expect { query_results.work_package_count_by_group }.not_to raise_error
end
end
context 'grouping by type' do
let(:group_by) { 'type' }
before do
work_package1
work_package2
login_as(user_1)
end
it 'returns the groups sorted by type`s position' do
type_1.update_column(:position, 1)
type_2.update_column(:position, 2)
result = query_results.work_package_count_by_group
expect(result.length)
.to eql 2
expect(result.keys.map(&:id))
.to eql [type_1.id, type_2.id]
type_1.update_column(:position, 2)
type_2.update_column(:position, 1)
new_results = ::Query::Results.new(query)
result = new_results.work_package_count_by_group
expect(result.length)
.to eql 2
expect(result.keys.map(&:id))
.to eql [type_2.id, type_1.id]
end
end
context 'grouping by list custom field and filtering for it at the same time' do
let!(:custom_field) do
FactoryBot.create(:list_wp_custom_field,
is_for_all: true,
is_filter: true,
multi_value: true).tap do |cf|
work_package1.type.custom_fields << cf
work_package2.type.custom_fields << cf
end
end
let(:first_value) do
custom_field.custom_options.first
end
let(:last_value) do
custom_field.custom_options.last
end
let(:group_by) { "cf_#{custom_field.id}" }
before do
login_as(user_1)
work_package1.send(:"custom_field_#{custom_field.id}=", first_value)
work_package1.save!
work_package2.send(:"custom_field_#{custom_field.id}=", [first_value,
last_value])
work_package2.save!
end
it 'yields no error but rather returns the result' do
expect { query_results.work_package_count_by_group }.not_to raise_error
group_count = query_results.work_package_count_by_group
expected_groups = [[first_value], [first_value, last_value]]
group_count.each do |key, count|
expect(count).to eql 1
expect(expected_groups.any? { |group| group & key == key & group }).to be_truthy
end
end
end
context 'grouping by int custom field' do
let!(:custom_field) do
FactoryBot.create(:int_wp_custom_field, is_for_all: true, is_filter: true)
end
let(:group_by) { "cf_#{custom_field.id}" }
before do
login_as(user_1)
wp_p1[0].type.custom_fields << custom_field
project_1.work_package_custom_fields << custom_field
wp_p1[0].update_attribute(:"custom_field_#{custom_field.id}", 42)
wp_p1[0].save
wp_p1[1].update_attribute(:"custom_field_#{custom_field.id}", 42)
wp_p1[1].save
end
it 'returns a hash of counts by value' do
expect(query_results.work_package_count_by_group).to eql(42 => 2, nil => 1)
end
end
context 'grouping by user custom field' do
let!(:custom_field) do
FactoryBot.create(:user_wp_custom_field, is_for_all: true, is_filter: true)
end
let(:group_by) { "cf_#{custom_field.id}" }
before do
login_as(user_1)
wp_p1[0].type.custom_fields << custom_field
project_1.work_package_custom_fields << custom_field
end
it 'returns nil as user custom fields are not groupable' do
expect(query_results.work_package_count_by_group).to be_nil
end
end
context 'grouping by bool custom field' do
let!(:custom_field) do
FactoryBot.create(:bool_wp_custom_field, is_for_all: true, is_filter: true)
end
let(:group_by) { "cf_#{custom_field.id}" }
before do
login_as(user_1)
wp_p1[0].type.custom_fields << custom_field
project_1.work_package_custom_fields << custom_field
wp_p1[0].update_attribute(:"custom_field_#{custom_field.id}", true)
wp_p1[0].save
wp_p1[1].update_attribute(:"custom_field_#{custom_field.id}", true)
wp_p1[1].save
end
it 'returns a hash of counts by value' do
expect(query_results.work_package_count_by_group).to eql(true => 2, nil => 1)
end
end
context 'grouping by date custom field' do
let!(:custom_field) do
FactoryBot.create(:date_wp_custom_field, is_for_all: true, is_filter: true)
end
let(:group_by) { "cf_#{custom_field.id}" }
before do
login_as(user_1)
wp_p1[0].type.custom_fields << custom_field
project_1.work_package_custom_fields << custom_field
wp_p1[0].update_attribute(:"custom_field_#{custom_field.id}", Date.today)
wp_p1[0].save
wp_p1[1].update_attribute(:"custom_field_#{custom_field.id}", Date.today)
wp_p1[1].save
end
it 'returns a hash of counts by value' do
expect(query_results.work_package_count_by_group).to eql(Date.today => 2, nil => 1)
end
end
end
describe '#work_packages' do
@ -587,85 +765,4 @@ describe ::Query::Results, type: :model do
end
end
end
context 'when grouping by custom field' do
let!(:custom_field) do
FactoryBot.create(:int_wp_custom_field, is_for_all: true, is_filter: true)
end
before do
allow(User).to receive(:current).and_return(user_1)
wp_p1[0].type.custom_fields << custom_field
project_1.work_package_custom_fields << custom_field
wp_p1[0].update_attribute(:"custom_field_#{custom_field.id}", 42)
wp_p1[0].save
wp_p1[1].update_attribute(:"custom_field_#{custom_field.id}", 42)
wp_p1[1].save
query.project = project_1
query.group_by = "cf_#{custom_field.id}"
end
describe '#work_package_count_by_group' do
it 'returns a hash of counts by value' do
expect(query.results.work_package_count_by_group).to eql(42 => 2, nil => 1)
end
end
end
context 'when grouping by list custom field and filtering for it at the same time' do
let!(:custom_field) do
FactoryBot.create(:list_wp_custom_field,
is_for_all: true,
is_filter: true,
multi_value: true).tap do |cf|
work_package1.type.custom_fields << cf
end
end
let(:first_value) do
custom_field.custom_options.first
end
let(:last_value) do
custom_field.custom_options.last
end
let(:work_package1) do
FactoryBot.create(:work_package,
project: project_1)
end
let(:work_package2) do
FactoryBot.create(:work_package,
type: work_package1.type,
project: project_1)
end
before do
allow(User).to receive(:current).and_return(user_1)
query.group_by = "cf_#{custom_field.id}"
query.project = project_1
work_package1.send(:"custom_field_#{custom_field.id}=", first_value)
work_package1.save!
work_package2.send(:"custom_field_#{custom_field.id}=", [first_value,
last_value])
work_package2.save!
end
describe '#work_package_count_by_group' do
it 'yields no error but rather returns the result' do
expect { query.results.work_package_count_by_group }.not_to raise_error
group_count = query.results.work_package_count_by_group
expected_groups = [[first_value], [first_value, last_value]]
group_count.each do |key, count|
expect(count).to eql 1
expect(expected_groups.any? { |group| group & key == key & group }).to be_truthy
end
end
end
end
end

@ -67,7 +67,7 @@ describe WorkPackage, type: :model do
journal_ids.clear
work_package.update_attributes subject: 'the wind of change'
work_package.update subject: 'the wind of change'
end
it "are triggered" do

@ -60,7 +60,7 @@ describe WorkPackage, type: :model do
end
it 'sends one delayed mail notification for each watcher recipient' do
work_package.update_attributes description: 'Any new description'
work_package.update description: 'Any new description'
end
end
end

@ -72,7 +72,7 @@ describe WorkPackage, type: :model do
describe 'after update' do
before do
work_package.update_attributes subject: 'the wind of change'
work_package.update subject: 'the wind of change'
end
it "are sent to the work package's author" do

@ -34,13 +34,6 @@ require 'shoulda/matchers'
require 'rspec/example_disabler'
require 'test_prof/recipes/rspec/before_all'
##
# Start collecting coverage when desired
if ENV['COVERAGE']
require 'simplecov'
SimpleCov.start 'rails'
end
# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end

@ -36,10 +36,10 @@ module Components
def confirm_flow_with(password, should_fail: false)
expect_open
expect(submit_button[:disabled]).to be_truthy
expect(submit_button).to be_disabled
fill_in 'request_for_confirmation_password', with: password
expect(submit_button[:disabled]).to be_falsey
expect(submit_button).not_to be_disabled
submit(should_fail)
end

@ -27,7 +27,7 @@ shared_examples_for 'repository can be relocated' do |vendor|
expect(Dir.exists?(repository.managed_repository_path)).to be true
# Rename the project
project.update_attributes!(identifier: 'somenewidentifier')
project.update!(identifier: 'somenewidentifier')
repository.reload
job.perform

@ -132,7 +132,7 @@ MESSAGE
context 'when it is a public project' do
before do
project.update_attributes is_public: true
project.update is_public: true
model_instance.reload
end
@ -150,7 +150,7 @@ MESSAGE
context 'when it is a private project' do
before do
project.update_attributes is_public: false
project.update is_public: false
model_instance.reload
end
@ -241,7 +241,7 @@ MESSAGE
context 'when it is a public project' do
before do
project.update_attributes is_public: true
project.update is_public: true
model_instance.reload
end
@ -275,7 +275,7 @@ MESSAGE
context 'when it is a private project' do
before do
project.update_attributes is_public: false
project.update is_public: false
model_instance.reload
end

@ -31,7 +31,7 @@
def aggregate_mocked_settings(example, settings)
# We have to manually check parent groups for with_settings:,
# since they are being ignored otherwise
example.example_group.parents.each do |parent|
example.example_group.module_parents.each do |parent|
if parent.respond_to?(:metadata) && parent.metadata[:with_settings]
settings.reverse_merge!(parent.metadata[:with_settings])
end

@ -63,18 +63,18 @@ describe Enumeration, type: :model do
end
it 'should update default' do
@default_enumeration.update_attributes(name: 'Changed', is_default: true)
@default_enumeration.update(name: 'Changed', is_default: true)
assert_equal @default_enumeration, Enumeration.default
end
it 'should update default to non default' do
@default_enumeration.update_attributes(name: 'Changed', is_default: false)
@default_enumeration.update(name: 'Changed', is_default: false)
assert_nil Enumeration.default
end
it 'should change default' do
e = Enumeration.find_by(name: @default_enumeration.name)
e.update_attributes(name: 'Changed Enumeration', is_default: true)
e.update(name: 'Changed Enumeration', is_default: true)
assert_equal e, Enumeration.default
end

@ -176,6 +176,6 @@ describe 'Redmine::Hook::Manager' do # FIXME: naming (RSpec-port)
end
def view_hook_helper
@view_hook_helper ||= TestHookHelperView.new(Rails.root.to_s + '/app/views')
@view_hook_helper ||= TestHookHelperView.new(ActionView::LookupContext.new(Rails.root.to_s + '/app/views'))
end
end

@ -258,27 +258,6 @@ describe Query, type: :model do
assert q.has_column?(c)
end
it 'should groupable columns should include custom fields' do
q = Query.new name: '_'
assert q.groupable_columns.detect { |c| c.is_a? Queries::WorkPackages::Columns::CustomFieldColumn }
end
it 'should grouped with valid column' do
q = Query.new(group_by: 'status', name: '_')
assert q.grouped?
refute_nil q.group_by_column
assert_equal :status, q.group_by_column.name
refute_nil q.group_by_statement
assert_equal 'status', q.group_by_statement
end
it 'should grouped with invalid column' do
q = Query.new(group_by: 'foo', name: '_')
assert !q.grouped?
assert_nil q.group_by_column
assert_nil q.group_by_statement
end
it 'should default sort' do
q = Query.new name: '_'
assert_equal [], q.sort_criteria
@ -347,50 +326,6 @@ describe Query, type: :model do
assert_equal values.sort, values
end
it 'should invalid query should raise query statement invalid error' do
q = Query.new name: '_'
assert_raises ActiveRecord::StatementInvalid do
q.results(conditions: 'foo = 1').work_packages.to_a
end
end
it 'should issue count by association group' do
q = Query.new(name: '_',
group_by: 'assigned_to',
show_hierarchies: false)
count_by_group = q.results.work_package_count_by_group
assert_kind_of Hash, count_by_group
assert_equal %w(NilClass User), count_by_group.keys.map { |k| k.class.name }.uniq.sort
assert_equal %w(Integer), count_by_group.values.map { |k| k.class.name }.uniq
assert count_by_group.has_key?(User.find(3))
end
it 'should issue count by list custom field group' do
q = Query.new(name: '_',
group_by: 'cf_1',
show_hierarchies: false)
count_by_group = q.results.work_package_count_by_group
assert_kind_of Hash, count_by_group
expect(count_by_group.keys.map { |k| k.class.name }.uniq)
.to match_array(%w(CustomOption NilClass))
assert_equal %w(Integer), count_by_group.values.map { |k| k.class.name }.uniq
expect(count_by_group.any? { |k, v| k.is_a?(CustomOption) && k.id == 1 && v == 1 })
.to be_truthy
end
it 'should issue count by date custom field group' do
q = Query.new(name: '_',
group_by: 'cf_8',
show_hierarchies: false)
count_by_group = q.results.work_package_count_by_group
assert_kind_of Hash, count_by_group
assert_equal %w(Date NilClass), count_by_group.keys.map { |k| k.class.name }.uniq.sort
assert_equal %w(Integer), count_by_group.values.map { |k| k.class.name }.uniq
end
context '#filter_for' do
before do
@query = Query.new(name: '_')

Loading…
Cancel
Save