diff --git a/.annotaterb.yml b/.annotaterb.yml new file mode 100644 index 0000000000..0f4129c32e --- /dev/null +++ b/.annotaterb.yml @@ -0,0 +1,71 @@ +--- +:position: before +:position_in_additional_file_patterns: before +:position_in_class: before +:position_in_factory: before +:position_in_fixture: before +:position_in_routes: before +:position_in_serializer: before +:position_in_test: before +:classified_sort: true +:exclude_controllers: true +:exclude_factories: false +:exclude_fixtures: true +:exclude_helpers: true +:exclude_scaffolds: true +:exclude_serializers: true +:exclude_sti_subclasses: false +:exclude_tests: true +:force: false +:format_markdown: false +:format_rdoc: false +:format_yard: false +:frozen: false +:grouped_polymorphic: false +:ignore_database_name: false +:ignore_model_sub_dir: false +:ignore_unknown_models: false +:include_version: false +:show_check_constraints: false +:show_unique_constraints: false +:show_exclusion_constraints: false +:show_enums: false +:show_complete_foreign_keys: false +:show_foreign_keys: true +:show_indexes: true +:show_indexes_comments: false +:show_indexes_include: false +:simple_indexes: false +:sort: false +:timestamp: false +:trace: false +:with_comment: true +:with_column_comments: true +:with_table_comments: true +:position_of_column_comment: :with_name +:active_admin: false +:command: +:debug: false +:hide_default_column_types: json,jsonb,hstore +:hide_limit_column_types: integer,boolean +:timestamp_columns: +- created_at +- updated_at +:ignore_columns: +:ignore_routes: +:ignore_multi_database_name: false +:models: true +:routes: false +:skip_on_db_migrate: false +:auto_annotate_routes_after_migrate: false +:target_action: :do_annotations +:wrapper: +:wrapper_close: +:wrapper_open: +:classes_default_to_s: [] +:additional_file_patterns: [] +:model_dir: +- app/models +:require: [] +:root_dir: +- '' diff --git a/.github/workflows/brakeman.yml b/.github/workflows/brakeman.yml index 52ecd71cf1..1ba5268110 100644 --- a/.github/workflows/brakeman.yml +++ b/.github/workflows/brakeman.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 # Will run Brakeman checks on dependencies # https://github.com/marketplace/actions/brakeman-action diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index 650ac6720e..8b64400fe5 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: 'Determine Ruby and Bundler Versions from Gemfile.lock' run: | @@ -27,4 +27,4 @@ jobs: - name: 'Run Danger' env: DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: bundle exec danger \ No newline at end of file + run: bundle exec danger diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml index a3aa258eae..e29efe6a6f 100644 --- a/.github/workflows/eslint.yml +++ b/.github/workflows/eslint.yml @@ -9,17 +9,23 @@ jobs: steps: # Checkout the repo - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 # Install Node - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v5 with: cache: 'yarn' - node-version: 18 + node-version: 24 # Run yarn install for JS dependencies - name: 'Yarn Install' - run: yarn install + run: yarn install --frozen-lockfile - name: 'Run ESLint' - run: yarn run eslint app/javascript/**/*.js --ext .js + run: yarn lint + + - name: 'Run JavaScript tests' + run: yarn test --reporters dots + + - name: 'Build CSS' + run: yarn build:css diff --git a/.github/workflows/mysql.yml b/.github/workflows/mysql.yml index 7c25271528..7df099a8ef 100644 --- a/.github/workflows/mysql.yml +++ b/.github/workflows/mysql.yml @@ -14,7 +14,7 @@ jobs: steps: # Checkout the repo - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 # Install Ruby and run bundler - uses: ruby/setup-ruby@v1 @@ -22,9 +22,9 @@ jobs: bundler-cache: true # Install Node - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v5 with: - node-version: 18 + node-version: 24 cache: 'yarn' # Copy all of the example configs over @@ -45,7 +45,7 @@ jobs: # Run yarn install for JS dependencies - name: 'Yarn Install' - run: yarn install + run: yarn install --frozen-lockfile # Start the DB server and initialize the DB - name: 'Start MySQL' @@ -53,8 +53,8 @@ jobs: - name: 'Build out the test database' run: | - DISABLE_SPRING=1 bundle exec rails db:create RAILS_ENV=test - DISABLE_SPRING=1 bundle exec rails db:schema:load RAILS_ENV=test + bundle exec rails db:create RAILS_ENV=test + bundle exec rails db:schema:load RAILS_ENV=test - name: 'Run any pending database migrations' run: bin/rails db:migrate RAILS_ENV=test diff --git a/.github/workflows/postgres.yml b/.github/workflows/postgres.yml index dbc9d73ba1..1a731f12d9 100644 --- a/.github/workflows/postgres.yml +++ b/.github/workflows/postgres.yml @@ -9,7 +9,7 @@ jobs: services: # Postgres installation db: - image: postgres + image: postgres:16 env: # Latest version of Postgres has increased security. We can use the default # user/password in this testing scenario though so use the following env @@ -27,11 +27,10 @@ jobs: env: RAILS_ENV: test DATABASE_URL: postgres://postgres:@localhost:5432/roadmap_test - DISABLE_SPRING: 1 steps: # Checkout the repo - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 # Install Ruby and run bundler - uses: ruby/setup-ruby@v1 @@ -42,9 +41,9 @@ jobs: ## /home/runner/runners/2.301.1/externals/node12/bin/node: --openssl-legacy-provider is not allowed in NODE_OPTIONS # Install Node - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v5 with: - node-version: 18 + node-version: 24 cache: "yarn" # Install the Postgres developer packages @@ -79,15 +78,16 @@ jobs: # Run yarn install for JS dependencies - name: "Yarn Install" run: | - yarn install + yarn install --frozen-lockfile # TEMPORARY WORKAROUND FOR THE FOLLOWING ISSUE: https://github.com/DMPRoadmap/roadmap/issues/3485 # Remove this once our tests are compatible with the new version of Chrome # Source: https://github.com/teamcapybara/capybara/issues/2800#issuecomment-2731100953 - name: Remove image-bundled Chrome run: sudo apt-get purge google-chrome-stable - - name: Setup stable Chrome - uses: browser-actions/setup-chrome@v1 + - name: Setup Chrome 128 + id: setup-chrome + uses: browser-actions/setup-chrome@v2 with: chrome-version: 128 install-chromedriver: true @@ -99,6 +99,12 @@ jobs: bundle exec rails db:setup bundle exec rails db:migrate + # PostgreSQL is the canonical source of the shared schema.rb. + - name: "Check schema drift" + run: | + bundle exec rails db:schema:dump + git diff --exit-code -- db/schema.rb + # Prebuild the CSS, JS and image assets - name: "Compile Assets" run: bundle exec rails assets:precompile @@ -112,4 +118,9 @@ jobs: # Run the time consuming integration tests (using Chrome headless browser) - name: "Run Integration Tests" - run: bundle exec rspec spec/features/ + env: + CHROME_BIN: ${{ steps.setup-chrome.outputs.chrome-path }} + run: | + "$CHROME_BIN" --version + chromedriver --version + bundle exec rspec spec/features/ diff --git a/.github/workflows/rubocop.yml b/.github/workflows/rubocop.yml index 15c3fd9028..1570e50ebc 100644 --- a/.github/workflows/rubocop.yml +++ b/.github/workflows/rubocop.yml @@ -8,7 +8,7 @@ jobs: steps: # Checkout the repo - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 # Install Ruby and run bundler - uses: ruby/setup-ruby@v1 diff --git a/.gitignore b/.gitignore index b32c4f2b28..61355c0a3a 100644 --- a/.gitignore +++ b/.gitignore @@ -116,3 +116,6 @@ yarn-debug.log* # Ignore briley AWS cloud9 script to start the application cloud9-start.sh + +# Ignore key files for decrypting credentials and more. +/config/*.key diff --git a/.node-version b/.node-version new file mode 100644 index 0000000000..ca5c350055 --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +24.18.0 diff --git a/.rubocop.yml b/.rubocop.yml index 40f584cdac..6828ce92ce 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -29,6 +29,7 @@ plugins: - rubocop-performance AllCops: + TargetRubyVersion: 3.4 # Show the name of the cops being voilated in the feedback DisplayCopNames: true DisplayStyleGuide: true diff --git a/.ruby-version b/.ruby-version index 0aec50e6ed..0ce07b72f8 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.1.4 +3.4.11 diff --git a/CHANGELOG.md b/CHANGELOG.md index a344d9bbec..e83731be73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## v6.0.0 + +- Upgrade the required runtime from Ruby 3.1/Rails 7.1 to Ruby 3.4/Rails 8.1 + and update compatible gems. This release adds no product features or API + versions. +- Adapt existing authentication, enums, routes, exports, and schema dumping + for the new framework versions. Continue to support PostgreSQL and MySQL. +- Update CI for Node 24, asset builds, and PostgreSQL schema drift checks; + add regression coverage for API headers, DOCX exports, and permission flags. +- Replace the Ruby 3.4-incompatible model annotation tool and remove Spring. + ## v5.0.3 - Patch API token auth to check user's status [#3606](https://github.com/DMPRoadmap/roadmap/pull/3606) - fix(policy): harden authorization for plan resources [#3613](https://github.com/DMPRoadmap/roadmap/pull/3613) diff --git a/Gemfile b/Gemfile index 2a9aa8721d..5929beab5c 100644 --- a/Gemfile +++ b/Gemfile @@ -2,20 +2,17 @@ source 'https://rubygems.org' -ruby '3.1.4' +ruby '~> 3.4.0' + +# Ruby 3.4 ships CSV separately; exports and statistics require it directly. +gem 'csv' # ===========# # CORE RAILS # # ===========# # Full-stack web application framework. (http://rubyonrails.org) -gem 'rails', '~> 7.1' - -# TODO: Remove this once Rails addresses the issue with its dependency on mimemagic. Mimemagic had -# an MIT license but was using some incompatible GPL license code. -# Versions of mimemagic that were yanked: https://rubygems.org/gems/mimemagic/versions -# Analysis of the issue: https://www.theregister.com/2021/03/25/ruby_rails_code/ -gem 'mimemagic' +gem 'rails', '~> 8.1.0' # Use Puma as the app server gem 'puma', group: :puma, require: false @@ -31,10 +28,10 @@ gem 'cssbundling-rails' # Turbo gives you the speed of a single-page web application without having to write any JavaScript.. # Read more: https://github.com/hotwired/turbo-rails # https://github.com/hotwired/turbo-rails/blob/main/UPGRADING.md -gem 'turbo-rails' +gem 'turbo-rails', '~> 2.0' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder -gem 'jbuilder' +gem 'jbuilder', '~> 2.15' # Use Redis adapter to run Action Cable in production # gem "redis", "~> 4.0" @@ -47,10 +44,6 @@ gem 'jbuilder' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', require: false -# The ultimate text progress bar library for Ruby! -# (https://github.com/jfelchner/ruby-progressbar) -gem 'ruby-progressbar' - # Provides Sprockets implementation for Rails 4.x (and beyond) Asset Pipeline. # https://github.com/rails/sprockets-rails gem 'sprockets-rails' @@ -85,7 +78,7 @@ gem 'flag_shih_tzu' # , "~> 0.3.23" # Flexible authentication solution for Rails with Warden # (https://github.com/plataformatec/devise) -gem 'devise' +gem 'devise', '~> 5.0' # An invitation strategy for Devise (https://github.com/scambra/devise_invitable) gem 'devise_invitable' @@ -205,14 +198,15 @@ gem 'dotenv-rails' gem 'activerecord_json_validator' -# We need to freeze the mail gem version as the recently released 2.8.0 triggers an exception -# We will need to check if it's fixed when we migrate to Ruby 3.0/3.1 -# See : https://github.com/DMPRoadmap/roadmap/issues/3254 -gem 'mail', '2.7.1' +gem 'logger', '~> 1.7' +gem 'mail' # This library provides functionality to send internet mail via SMTP, the Simple Mail Transfer Protocol. # https://github.com/ruby/net-smtp -gem 'net-smtp' +gem 'net-imap', '~> 0.5' +gem 'net-pop', '~> 0.1' +gem 'net-smtp', '~> 0.5' +gem 'rake', '~> 13.4' # ================================= # # ENVIRONMENT SPECIFIC DEPENDENCIES # @@ -220,12 +214,12 @@ gem 'net-smtp' group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console - gem 'byebug', platforms: %i[mri mingw x64_mingw] + gem 'byebug', platforms: %i[mri windows] end group :test do # RSpec for Rails (https://github.com/rspec/rspec-rails) - gem 'rspec-rails' + gem 'rspec-rails', '~> 8.0' # factory_bot_rails provides integration between factory_bot and rails 3 # or newer (http://github.com/thoughtbot/factory_bot_rails) @@ -260,7 +254,7 @@ group :test do gem 'capybara' # Easy installation and use of web drivers to run system tests with browsers - gem 'selenium-webdriver' + gem 'selenium-webdriver', '~> 4.25' # RSpec::CollectionMatchers lets you express expected outcomes on # collections of an object in an example. @@ -288,25 +282,21 @@ group :ci, :development do # RuboCop is a Ruby code style checking and code formatting tool. It aims to enforce # the community-driven Ruby Style Guide. - gem 'rubocop' + # Keep Roadmap's established lint rules during the runtime upgrade. + gem 'rubocop', '~> 1.81.0' # RuboCop rules for detecting and autocorrecting undecorated strings for i18n # (gettext and rails-i18n) gem 'rubocop-i18n' # Performance checks by Rubocop - gem 'rubocop-performance', require: false + gem 'rubocop-performance', '~> 1.26.0', require: false end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'listen' gem 'web-console' - # Spring speeds up development by keeping your application running in the background. - # Read more: https://github.com/rails/spring - gem 'spring' - gem 'spring-watcher-listen' - # Simple Progress Bar for output to a terminal # (http://github.com/paul/progress_bar) gem 'progress_bar', require: false @@ -322,16 +312,11 @@ group :development do # even further up the stack. (http://github.com/banister/binding_of_caller) gem 'binding_of_caller' - # rspec command for spring - # (https://github.com/jonleighton/spring-commands-rspec) - gem 'spring-commands-rspec' - # Profiles loading speed for rack applications. (http://miniprofiler.com) gem 'rack-mini-profiler' - # Annotates Rails Models, routes, fixtures, and others based on the - # database schema. (http://github.com/ctran/annotate_models) - gem 'annotate' + # Annotates models from the database schema under Rails 8. + gem 'annotaterb', '~> 4.24.0' # Add comments to your Gemfile with each dependency's description. # (https://github.com/ivantsepp/annotate_gem) diff --git a/Gemfile.lock b/Gemfile.lock index 56db857b5c..08bc08896e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,122 +1,123 @@ GEM remote: https://rubygems.org/ specs: - actioncable (7.1.5.2) - actionpack (= 7.1.5.2) - activesupport (= 7.1.5.2) + action_text-trix (2.1.19) + railties + actioncable (8.1.4) + actionpack (= 8.1.4) + activesupport (= 8.1.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (7.1.5.2) - actionpack (= 7.1.5.2) - activejob (= 7.1.5.2) - activerecord (= 7.1.5.2) - activestorage (= 7.1.5.2) - activesupport (= 7.1.5.2) - mail (>= 2.7.1) - net-imap - net-pop - net-smtp - actionmailer (7.1.5.2) - actionpack (= 7.1.5.2) - actionview (= 7.1.5.2) - activejob (= 7.1.5.2) - activesupport (= 7.1.5.2) - mail (~> 2.5, >= 2.5.4) - net-imap - net-pop - net-smtp + actionmailbox (8.1.4) + actionpack (= 8.1.4) + activejob (= 8.1.4) + activerecord (= 8.1.4) + activestorage (= 8.1.4) + activesupport (= 8.1.4) + mail (>= 2.8.0) + actionmailer (8.1.4) + actionpack (= 8.1.4) + actionview (= 8.1.4) + activejob (= 8.1.4) + activesupport (= 8.1.4) + mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (7.1.5.2) - actionview (= 7.1.5.2) - activesupport (= 7.1.5.2) + actionpack (8.1.4) + actionview (= 8.1.4) + activesupport (= 8.1.4) nokogiri (>= 1.8.5) - racc rack (>= 2.2.4) rack-session (>= 1.0.1) rack-test (>= 0.6.3) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - actiontext (7.1.5.2) - actionpack (= 7.1.5.2) - activerecord (= 7.1.5.2) - activestorage (= 7.1.5.2) - activesupport (= 7.1.5.2) + useragent (~> 0.16) + actiontext (8.1.4) + action_text-trix (~> 2.1.15) + actionpack (= 8.1.4) + activerecord (= 8.1.4) + activestorage (= 8.1.4) + activesupport (= 8.1.4) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.1.5.2) - activesupport (= 7.1.5.2) + actionview (8.1.4) + activesupport (= 8.1.4) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (7.1.5.2) - activesupport (= 7.1.5.2) + activejob (8.1.4) + activesupport (= 8.1.4) globalid (>= 0.3.6) - activemodel (7.1.5.2) - activesupport (= 7.1.5.2) - activerecord (7.1.5.2) - activemodel (= 7.1.5.2) - activesupport (= 7.1.5.2) + activemodel (8.1.4) + activesupport (= 8.1.4) + activerecord (8.1.4) + activemodel (= 8.1.4) + activesupport (= 8.1.4) timeout (>= 0.4.0) activerecord_json_validator (3.1.0) activerecord (>= 4.2.0, < 9) json_schemer (~> 2.2) - activestorage (7.1.5.2) - actionpack (= 7.1.5.2) - activejob (= 7.1.5.2) - activerecord (= 7.1.5.2) - activesupport (= 7.1.5.2) + activestorage (8.1.4) + actionpack (= 8.1.4) + activejob (= 8.1.4) + activerecord (= 8.1.4) + activesupport (= 8.1.4) marcel (~> 1.0) - activesupport (7.1.5.2) + activesupport (8.1.4) base64 - benchmark (>= 0.3) bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) + concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + json logger (>= 1.4.2) minitest (>= 5.1) - mutex_m securerandom (>= 0.3) - tzinfo (~> 2.0) - addressable (2.8.7) - public_suffix (>= 2.0.2, < 7.0) - annotate (3.2.0) - activerecord (>= 3.2, < 8.0) - rake (>= 10.4, < 14.0) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) + addressable (2.9.0) + public_suffix (>= 2.0.2, < 8.0) annotate_gem (0.0.14) bundler (>= 1.1) - api-pagination (6.0.0) + annotaterb (4.24.0) + activerecord (>= 6.0.0) + activesupport (>= 6.0.0) + anonymous_loader (0.1.3) + version_gem (~> 1.1, >= 1.1.14) + api-pagination (7.1.0) ast (2.4.3) + auth-sanitizer (0.2.3) + version_gem (~> 1.1, >= 1.1.14) autoprefixer-rails (10.4.21.0) execjs (~> 2) base64 (0.3.0) - bcrypt (3.1.20) - benchmark (0.4.1) + bcrypt (3.1.22) better_errors (2.10.1) erubi (>= 1.0.0) rack (>= 0.9.0) rouge (>= 1.0.0) - bigdecimal (3.3.0) + bigdecimal (4.1.3) bindex (0.8.1) - binding_of_caller (1.0.1) + binding_of_caller (2.0.0) debug_inspector (>= 1.2.0) - bootsnap (1.18.6) - msgpack (~> 1.2) - brakeman (7.1.0) + bootsnap (1.26.0) + msgpack (~> 1.5) + brakeman (8.1.0) racc builder (3.3.0) - bullet (8.0.8) + bullet (8.2.0) activesupport (>= 3.0.0) uniform_notifier (~> 1.11) - bundle-audit (0.1.0) + bundle-audit (0.2.0) bundler-audit - bundler-audit (0.9.2) - bundler (>= 1.2.0, < 3) + bundler-audit (0.9.3) + bundler (>= 1.2.0) thor (~> 1.0) - byebug (12.0.0) + byebug (13.0.0) + reline (>= 0.6.0) capybara (3.40.0) addressable matrix @@ -126,7 +127,6 @@ GEM rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - cgi (0.5.0) claide (1.1.0) claide-plugins (0.9.2) cork @@ -134,20 +134,20 @@ GEM open4 (~> 1.3) coderay (1.1.3) colored2 (3.1.2) - concurrent-ruby (1.3.5) - connection_pool (2.5.4) + concurrent-ruby (1.3.8) + connection_pool (3.0.2) contact_us (1.2.0) rails (>= 4.2.0) cork (0.3.0) colored2 (~> 3.1) - crack (1.0.0) + crack (1.0.1) bigdecimal rexml - crass (1.0.6) + crass (1.0.7) cssbundling-rails (1.4.3) railties (>= 6.0.0) - csv (3.3.5) - danger (9.5.3) + csv (3.3.6) + danger (9.6.1) base64 (~> 0.2) claide (~> 1.0) claide-plugins (>= 0.9.2) @@ -155,7 +155,7 @@ GEM cork (~> 0.1) faraday (>= 0.9.0, < 3.0) faraday-http-cache (~> 2.0) - git (>= 1.13, < 3.0) + git (>= 1.13) kramdown (>= 2.5.1, < 3.0) kramdown-parser-gfm (~> 1.0) octokit (>= 4.0) @@ -166,24 +166,24 @@ GEM database_cleaner-active_record (2.2.2) activerecord (>= 5.a) database_cleaner-core (~> 2.0) - database_cleaner-core (2.0.1) - date (3.4.1) + database_cleaner-core (2.1.0) + date (3.5.1) debug_inspector (1.2.0) - devise (4.9.4) + devise (5.0.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) - railties (>= 4.1.0) + railties (>= 7.0) responders warden (~> 1.2.3) - devise_invitable (2.0.11) + devise_invitable (2.0.14) actionmailer (>= 5.0) devise (>= 4.6) diff-lcs (1.6.2) - dotenv (3.1.8) - dotenv-rails (3.1.8) - dotenv (= 3.1.8) + dotenv (3.2.0) + dotenv-rails (3.2.0) + dotenv (= 3.2.0) railties (>= 6.1) - dragonfly (1.4.1) + dragonfly (1.4.2) addressable (~> 2.3) multi_json (~> 1.0) ostruct (~> 0.6.1) @@ -192,31 +192,34 @@ GEM dragonfly (~> 1.0) fog-aws drb (2.2.3) - erb (4.0.4) - cgi (>= 0.3.3) + erb (6.0.7) erubi (1.13.1) - excon (1.3.0) + excon (1.7.2) logger - execjs (2.10.0) - factory_bot (6.5.5) + execjs (2.10.2) + json (>= 2) + factory_bot (6.6.0) activesupport (>= 6.1.0) factory_bot_rails (6.5.1) factory_bot (~> 6.5) railties (>= 6.1.0) - faker (3.5.2) + faker (3.8.0) i18n (>= 1.8.11, < 2) - faraday (2.14.0) + faraday (2.14.4) faraday-net_http (>= 2.0, < 3.5) json logger - faraday-http-cache (2.5.1) + faraday-http-cache (2.8.0) faraday (>= 0.8) - faraday-net_http (3.4.1) - net-http (>= 0.5.0) - ffi (1.17.2-arm64-darwin) - ffi (1.17.2-x86_64-linux-gnu) - flag_shih_tzu (0.3.23) - fog-aws (3.33.0) + faraday-net_http (3.4.4) + net-http (~> 0.5) + ffi (1.17.4-aarch64-linux-gnu) + ffi (1.17.4-arm64-darwin) + ffi (1.17.4-x86_64-linux-gnu) + fiddle (1.1.8) + flag_shih_tzu (1.0.6) + version_gem (~> 1.1, >= 1.1.15) + fog-aws (3.33.4) base64 (>= 0.2, < 0.4) fog-core (~> 2.6) fog-json (~> 1.1) @@ -226,15 +229,15 @@ GEM excon (~> 1.0) formatador (>= 0.2, < 2.0) mime-types - fog-json (1.2.0) + fog-json (1.5.0) fog-core - multi_json (~> 1.10) + json (>= 2.19, < 4) fog-xml (0.1.5) fog-core nokogiri (>= 1.5.11, < 2.0.0) - formatador (1.2.1) + formatador (1.2.3) reline - forwardable (1.3.3) + forwardable (1.4.0) fuubar (2.5.1) rspec-core (~> 3.0) ruby-progressbar (~> 1.4) @@ -244,56 +247,57 @@ GEM prime racc text (>= 1.3.0) - git (2.3.3) + git (5.6.0) activesupport (>= 5.0) addressable (~> 2.8) - process_executer (~> 1.1) - rchardet (~> 1.8) - globalid (1.3.0) + process_executer (~> 4.1) + rchardet (~> 1.9) + globalid (1.4.0) activesupport (>= 6.1) - guard (2.19.1) + guard (2.20.2) formatador (>= 0.2.4) listen (>= 2.7, < 4.0) logger (~> 1.6) lumberjack (>= 1.0.12, < 2.0) nenv (~> 0.1) notiffany (~> 0.0) - ostruct (~> 0.6) pry (>= 0.13.0) shellany (~> 0.0) thor (>= 0.18.1) hana (1.3.7) hashdiff (1.2.1) - hashie (5.0.0) + hashie (5.1.0) + logger highline (3.1.2) reline htmltoword (1.1.1) actionpack nokogiri rubyzip (>= 1.0) - httparty (0.23.1) + httparty (0.24.3) csv mini_mime (>= 1.0.0) multi_xml (>= 0.5.2) - i18n (1.14.7) + i18n (1.15.2) concurrent-ruby (~> 1.0) - io-console (0.8.1) - irb (1.15.2) + io-console (0.9.4) + irb (1.18.0) pp (>= 0.6.0) + prism (>= 1.3.0) rdoc (>= 4.0.0) reline (>= 0.4.2) - jbuilder (2.14.1) + jbuilder (2.15.1) actionview (>= 7.0.0) activesupport (>= 7.0.0) jsbundling-rails (1.3.1) railties (>= 6.0.0) - json (2.15.1) - json_schemer (2.4.0) + json (2.21.2) + json_schemer (2.5.0) bigdecimal hana (~> 1.3) regexp_parser (~> 2.0) simpleidn (~> 0.2) - jwt (3.1.2) + jwt (3.3.0) base64 kaminari (1.2.2) activesupport (>= 4.1.0) @@ -307,75 +311,83 @@ GEM activerecord kaminari-core (= 1.2.2) kaminari-core (1.2.2) - kramdown (2.5.1) - rexml (>= 3.3.9) + kramdown (2.5.2) + rexml (>= 3.4.4) kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) - language_server-protocol (3.17.0.5) + language_server-protocol (3.17.0.6) ledermann-rails-settings (2.6.2) activerecord (>= 6.1) lint_roller (1.1.0) - listen (3.9.0) + listen (3.10.1) + logger rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - locale (2.1.4) + locale (2.1.5) + fiddle logger (1.7.0) - loofah (2.24.1) + loofah (2.25.2) crass (~> 1.0.2) nokogiri (>= 1.12.0) lumberjack (1.4.2) - mail (2.7.1) + mail (2.9.1) + logger mini_mime (>= 0.1.1) - marcel (1.1.0) + net-imap + net-pop + net-smtp + marcel (1.2.1) matrix (0.4.3) method_source (1.1.0) mime-types (3.7.0) logger mime-types-data (~> 3.2025, >= 3.2025.0507) - mime-types-data (3.2025.0924) - mimemagic (0.4.3) - nokogiri (~> 1) - rake + mime-types-data (3.2026.0929) mini_mime (1.1.5) - minitest (5.25.5) - mocha (2.7.1) + minitest (6.0.6) + drb (~> 2.0) + prism (~> 1.5) + mocha (3.1.0) ruby2_keywords (>= 0.0.5) - msgpack (1.8.0) - multi_json (1.17.0) - multi_xml (0.7.1) - bigdecimal (~> 3.1) - mutex_m (0.3.0) + msgpack (1.8.5) + multi_json (1.21.2) + multi_xml (0.9.1) + bigdecimal (>= 3.1, < 5) mysql2 (0.5.7) bigdecimal nap (1.1.0) nenv (0.3.0) - net-http (0.6.0) - uri - net-imap (0.5.12) + net-http (0.9.1) + uri (>= 0.11.1) + net-imap (0.6.7) date net-protocol net-pop (0.1.2) net-protocol - net-protocol (0.2.2) + net-protocol (0.4.0) timeout - net-smtp (0.5.1) + net-smtp (0.5.2) net-protocol - nio4r (2.7.4) - nokogiri (1.18.10-arm64-darwin) + nio4r (2.7.5) + nokogiri (1.19.4-aarch64-linux-gnu) + racc (~> 1.4) + nokogiri (1.19.4-arm64-darwin) racc (~> 1.4) - nokogiri (1.18.10-x86_64-linux-gnu) + nokogiri (1.19.4-x86_64-linux-gnu) racc (~> 1.4) notiffany (0.1.3) nenv (~> 0.1) shellany (~> 0.0) - oauth2 (2.0.17) + oauth2 (2.0.25) + anonymous_loader (~> 0.1, >= 0.1.3) + auth-sanitizer (~> 0.2, >= 0.2.3) faraday (>= 0.17.3, < 4.0) jwt (>= 1.0, < 4.0) logger (~> 1.2) multi_xml (~> 0.5) rack (>= 1.2, < 4) - snaky_hash (~> 2.0, >= 2.0.3) - version_gem (~> 1.1, >= 1.1.9) + snaky_hash (~> 2.0, >= 2.0.7) + version_gem (~> 1.1, >= 1.1.14) octokit (10.0.0) faraday (>= 1, < 3) sawyer (~> 0.9) @@ -384,13 +396,13 @@ GEM logger rack (>= 2.2.3) rack-protection - omniauth-oauth2 (1.8.0) - oauth2 (>= 1.4, < 3) + omniauth-oauth2 (1.9.0) + oauth2 (>= 2.0.2, < 3) omniauth (~> 2.0) omniauth-orcid (2.1.1) omniauth-oauth2 (~> 1.3) ruby_dig (~> 0.0.2) - omniauth-rails_csrf_protection (1.0.2) + omniauth-rails_csrf_protection (2.0.1) actionpack (>= 4.2) omniauth (~> 2.0) omniauth-shibboleth (1.3.0) @@ -399,32 +411,32 @@ GEM options (2.3.2) orm_adapter (0.5.0) ostruct (0.6.3) - parallel (1.27.0) - parser (3.3.9.0) + parallel (1.28.0) + parser (3.3.12.0) ast (~> 2.4.1) racc - pg (1.6.2-arm64-darwin) - pg (1.6.2-x86_64-linux) - pp (0.6.3) + pg (1.7.0-aarch64-linux) + pg (1.7.0-arm64-darwin) + pg (1.7.0-x86_64-linux) + pp (0.6.4) prettyprint prettyprint (0.2.0) prime (0.1.4) forwardable singleton - prism (1.5.1) - process_executer (1.3.0) + prism (1.9.0) + process_executer (4.1.1) + track_open_instances (~> 0.1) progress_bar (1.3.4) highline (>= 1.6) options (~> 2.3.0) - pry (0.15.2) + pry (0.16.0) coderay (~> 1.1) method_source (~> 1.0) - pstore (0.2.0) - psych (5.2.6) - date - stringio - public_suffix (6.0.2) - puma (7.0.4) + reline (>= 0.6.0) + pstore (0.2.1) + public_suffix (7.0.5) + puma (8.0.2) nio4r (~> 2.0) pundit (2.5.2) activesupport (>= 3.0.0) @@ -434,36 +446,36 @@ GEM rspec-mocks (~> 3.12) rspec-support (~> 3.12) racc (1.8.1) - rack (3.2.2) - rack-attack (6.7.0) + rack (3.2.7) + rack-attack (6.8.0) rack (>= 1.0, < 4) - rack-mini-profiler (4.0.1) + rack-mini-profiler (5.0.0) rack (>= 1.2.0) - rack-protection (4.1.1) + rack-protection (4.2.1) base64 (>= 0.1.0) logger (>= 1.6.0) rack (>= 3.0.0, < 4) - rack-session (2.1.1) + rack-session (2.1.2) base64 (>= 0.1.0) rack (>= 3.0.0) rack-test (2.2.0) rack (>= 1.3) - rackup (2.2.1) + rackup (2.3.1) rack (>= 3) - rails (7.1.5.2) - actioncable (= 7.1.5.2) - actionmailbox (= 7.1.5.2) - actionmailer (= 7.1.5.2) - actionpack (= 7.1.5.2) - actiontext (= 7.1.5.2) - actionview (= 7.1.5.2) - activejob (= 7.1.5.2) - activemodel (= 7.1.5.2) - activerecord (= 7.1.5.2) - activestorage (= 7.1.5.2) - activesupport (= 7.1.5.2) + rails (8.1.4) + actioncable (= 8.1.4) + actionmailbox (= 8.1.4) + actionmailer (= 8.1.4) + actionpack (= 8.1.4) + actiontext (= 8.1.4) + actionview (= 8.1.4) + activejob (= 8.1.4) + activemodel (= 8.1.4) + activerecord (= 8.1.4) + activestorage (= 8.1.4) + activesupport (= 8.1.4) bundler (>= 1.15.0) - railties (= 7.1.5.2) + railties (= 8.1.4) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -472,57 +484,64 @@ GEM activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.6.2) - loofah (~> 2.21) + rails-html-sanitizer (1.7.1) + loofah (~> 2.25, >= 2.25.2) nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) - railties (7.1.5.2) - actionpack (= 7.1.5.2) - activesupport (= 7.1.5.2) - irb + railties (8.1.4) + actionpack (= 8.1.4) + activesupport (= 8.1.4) + irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) + tsort (>= 0.2) zeitwerk (~> 2.6) rainbow (3.1.1) - rake (13.3.0) + rake (13.4.2) rb-fsevent (0.11.2) rb-inotify (0.11.1) ffi (~> 1.0) - rchardet (1.10.0) - rdoc (6.15.0) + rbs (4.2.0) + logger + prism (>= 1.6.0) + tsort + rchardet (1.10.2) + rdoc (8.1.0) erb - psych (>= 4.0.0) + prism (>= 1.6.0) + rbs (>= 4.0.0) tsort - recaptcha (5.21.1) - regexp_parser (2.11.3) - reline (0.6.2) + recaptcha (5.21.2) + regexp_parser (2.13.1) + reline (0.7.0) io-console (~> 0.5) - responders (3.1.1) - actionpack (>= 5.2) - railties (>= 5.2) + responders (3.2.1) + actionpack (>= 7.0) + railties (>= 7.0) rexml (3.4.4) - rollbar (3.6.2) - rouge (4.6.1) + rollbar (3.8.0) + rouge (5.1.0) + strscan (~> 3.1) rspec-collection_matchers (1.2.1) rspec-expectations (>= 2.99.0.beta1) - rspec-core (3.13.5) + rspec-core (3.13.6) rspec-support (~> 3.13.0) rspec-expectations (3.13.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-mocks (3.13.5) + rspec-mocks (3.13.8) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-rails (7.1.1) - actionpack (>= 7.0) - activesupport (>= 7.0) - railties (>= 7.0) - rspec-core (~> 3.13) - rspec-expectations (~> 3.13) - rspec-mocks (~> 3.13) - rspec-support (~> 3.13) - rspec-support (3.13.6) - rubocop (1.81.1) + rspec-rails (8.0.4) + actionpack (>= 7.2) + activesupport (>= 7.2) + railties (>= 7.2) + rspec-core (>= 3.13.0, < 5.0.0) + rspec-expectations (>= 3.13.0, < 5.0.0) + rspec-mocks (>= 3.13.0, < 5.0.0) + rspec-support (>= 3.13.0, < 5.0.0) + rspec-support (3.13.7) + rubocop (1.81.7) json (~> 2.3) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.1.0) @@ -533,29 +552,28 @@ GEM rubocop-ast (>= 1.47.1, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.47.1) + rubocop-ast (1.50.0) parser (>= 3.3.7.2) - prism (~> 1.4) - rubocop-i18n (3.2.3) + prism (~> 1.7) + rubocop-i18n (3.3.0) lint_roller (~> 1.1) rubocop (>= 1.72.1) - rubocop-performance (1.26.0) + rubocop-performance (1.26.1) lint_roller (~> 1.1) rubocop (>= 1.75.0, < 2.0) - rubocop-ast (>= 1.44.0, < 2.0) + rubocop-ast (>= 1.47.1, < 2.0) ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) ruby_dig (0.0.2) - rubyzip (2.4.1) - sawyer (0.9.2) + rubyzip (3.7.0) + sawyer (0.9.3) addressable (>= 2.3.5) faraday (>= 0.17.3, < 3) securerandom (0.4.1) - selenium-webdriver (4.32.0) + selenium-webdriver (4.50.0) base64 (~> 0.2) logger (~> 1.4) - rexml (~> 3.2, >= 3.2.5) - rubyzip (>= 1.2.2, < 3.0) + rubyzip (>= 1.2.2, < 4.0) websocket (~> 1.0) shellany (0.0.1) shoulda (4.0.0) @@ -564,59 +582,54 @@ GEM shoulda-context (2.0.0) shoulda-matchers (4.5.1) activesupport (>= 4.2.0) - simpleidn (0.2.3) + simpleidn (0.3.0) singleton (0.3.0) - snaky_hash (2.0.3) + snaky_hash (2.0.7) hashie (>= 0.1.0, < 6) - version_gem (>= 1.1.8, < 3) - spring (4.4.0) - spring-commands-rspec (1.0.4) - spring (>= 0.9.1) - spring-watcher-listen (2.1.0) - listen (>= 2.7, < 4.0) - spring (>= 4) - sprockets (4.2.2) - concurrent-ruby (~> 1.0) + version_gem (~> 1.1, >= 1.1.14) + sprockets (4.4.1) + concurrent-ruby (~> 1.1) logger rack (>= 2.2.4, < 4) sprockets-rails (3.5.2) actionpack (>= 6.1) activesupport (>= 6.1) sprockets (>= 3.0.0) - stringio (3.1.7) + strscan (3.1.8) terminal-table (4.0.0) unicode-display_width (>= 1.1.1, < 4) text (1.3.1) - thor (1.4.0) - timeout (0.4.3) + thor (1.5.0) + timeout (0.6.1) tomparse (0.4.2) + track_open_instances (0.1.15) translation (1.41) gettext (~> 3.2, >= 3.2.5, <= 3.4.9) tsort (0.2.0) - turbo-rails (2.0.17) + turbo-rails (2.0.23) actionpack (>= 7.1.0) railties (>= 7.1.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicode-display_width (3.2.0) - unicode-emoji (~> 4.1) - unicode-emoji (4.1.0) + unicode-display_width (3.3.0) + unicode-emoji (~> 4.3) + unicode-emoji (4.3.0) uniform_notifier (1.18.0) - uri (1.0.4) - version_gem (1.1.9) + uri (1.1.1) + useragent (0.16.11) + version_gem (1.1.15) warden (1.2.9) rack (>= 2.0.9) - web-console (4.2.1) - actionview (>= 6.0.0) - activemodel (>= 6.0.0) + web-console (4.3.0) + actionview (>= 8.0.0) bindex (>= 0.4.0) - railties (>= 6.0.0) - webmock (3.25.1) + railties (>= 8.0.0) + webmock (3.26.4) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) websocket (1.2.11) - websocket-driver (0.8.0) + websocket-driver (0.8.2) base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) @@ -626,21 +639,23 @@ GEM wkhtmltopdf-binary (0.12.6.10) xpath (3.2.0) nokogiri (~> 1.8) - yard (0.9.37) + yard (0.9.45) yard-tomdoc (0.7.1) tomparse (>= 0.4.0) yard - zeitwerk (2.6.18) + zeitwerk (2.8.3) PLATFORMS + aarch64-linux arm64-darwin-21 arm64-darwin-22 + arm64-darwin-25 x86_64-linux DEPENDENCIES activerecord_json_validator - annotate annotate_gem + annotaterb (~> 4.24.0) api-pagination autoprefixer-rails better_errors @@ -653,9 +668,10 @@ DEPENDENCIES capybara contact_us cssbundling-rails + csv danger database_cleaner - devise + devise (~> 5.0) devise_invitable dotenv-rails dragonfly @@ -667,17 +683,19 @@ DEPENDENCIES guard htmltoword httparty - jbuilder + jbuilder (~> 2.15) jsbundling-rails jwt kaminari ledermann-rails-settings listen - mail (= 2.7.1) - mimemagic + logger (~> 1.7) + mail mocha mysql2 - net-smtp + net-imap (~> 0.5) + net-pop (~> 0.1) + net-smtp (~> 0.5) omniauth omniauth-orcid omniauth-rails_csrf_protection @@ -690,25 +708,22 @@ DEPENDENCIES pundit-matchers rack-attack (~> 6.6, >= 6.6.1) rack-mini-profiler - rails (~> 7.1) + rails (~> 8.1.0) rails-controller-testing + rake (~> 13.4) recaptcha rollbar rspec-collection_matchers - rspec-rails - rubocop + rspec-rails (~> 8.0) + rubocop (~> 1.81.0) rubocop-i18n - rubocop-performance - ruby-progressbar - selenium-webdriver + rubocop-performance (~> 1.26.0) + selenium-webdriver (~> 4.25) shoulda - spring - spring-commands-rspec - spring-watcher-listen sprockets-rails text translation - turbo-rails + turbo-rails (~> 2.0) web-console webmock wicked_pdf @@ -717,7 +732,7 @@ DEPENDENCIES yard-tomdoc RUBY VERSION - ruby 3.1.4p223 + ruby 3.4.11p137 BUNDLED WITH - 2.4.17 + 2.7.2 diff --git a/app/javascript/src/utils/tinymce.js b/app/javascript/src/utils/tinymce.js index c1112b1a35..9708ab9e90 100644 --- a/app/javascript/src/utils/tinymce.js +++ b/app/javascript/src/utils/tinymce.js @@ -119,9 +119,8 @@ export const Tinymce = { if (isString(className)) { const elements = Array.from(document.getElementsByClassName(className)); // Fetch the textarea elements and then return the TinyMCE editors associated with the element ids - return elements.map((el) => { - return Tinymce.findEditorById(el.getAttribute('id')); - }); + return elements.map((el) => Tinymce.findEditorById(el.getAttribute('id'))) + .filter((editor) => isTinymceEditor(editor)); } return []; }, @@ -133,7 +132,7 @@ export const Tinymce = { */ findEditorById(id) { if (isString(id)) { - return tinymce.get(id); + return tinymce.get(id) || undefined; } return undefined; }, diff --git a/app/models/annotation.rb b/app/models/annotation.rb index 4689352a0d..ed13669c0a 100644 --- a/app/models/annotation.rb +++ b/app/models/annotation.rb @@ -33,7 +33,7 @@ class Annotation < ApplicationRecord # I liked type as the name for the enum so overriding inheritance column self.inheritance_column = nil - enum type: %i[example_answer guidance] + enum :type, %i[example_answer guidance] # ================ # = Associations = diff --git a/app/models/api_client.rb b/app/models/api_client.rb index 0c20193c53..3bafc3ab18 100644 --- a/app/models/api_client.rb +++ b/app/models/api_client.rb @@ -4,25 +4,29 @@ # # Table name: api_clients # -# id :integer not null, primary key -# name :string, not null -# homepage :string -# contact_name :string -# contact_email :string, not null -# client_id :string, not null -# client_secret :string, not null -# last_access :datetime -# created_at :datetime -# updated_at :datetime -# org_id :integer +# id :integer not null, primary key +# callback_method :integer +# callback_uri :string +# client_secret :string not null +# confidential :boolean default(TRUE) +# contact_email :string +# contact_name :string +# description :string +# homepage :string +# last_access :datetime +# name :string not null +# redirect_uri :text +# scopes :string default(""), not null +# trusted :boolean default(FALSE) +# created_at :datetime not null +# updated_at :datetime not null +# client_id :string not null +# org_id :integer # # Indexes # -# index_api_clients_on_name (name) +# index_oauth_applications_on_name (name) # -# Foreign Keys -# -# fk_rails_... (org_id => orgs.id) # Object that represents an external system class ApiClient < ApplicationRecord diff --git a/app/models/condition.rb b/app/models/condition.rb index 4887de31df..963f962ba9 100644 --- a/app/models/condition.rb +++ b/app/models/condition.rb @@ -4,15 +4,15 @@ # # Table name: conditions # -# id :integer not null, primary key -# question_id :integer -# number :integer -# action_type :integer -# option_list :text -# remove_data :text -# webhook_data :text -# created_at :datetime not null -# updated_at :datetime not null +# id :integer not null, primary key +# action_type :integer +# number :integer +# option_list :text +# remove_data :text +# webhook_data :text +# created_at :datetime not null +# updated_at :datetime not null +# question_id :integer # # Indexes # @@ -20,8 +20,7 @@ # # Foreign Keys # -# fk_rails_... (question_id => question.id) -# +# fk_rails_... (question_id => questions.id) # # Object that represents a condition of a conditional question diff --git a/app/models/contributor.rb b/app/models/contributor.rb index 739d40aae7..3d80826e78 100644 --- a/app/models/contributor.rb +++ b/app/models/contributor.rb @@ -4,27 +4,24 @@ # # Table name: contributors # -# id :integer not null, primary key -# firstname :string -# surname :string -# email :string -# phone :string -# roles :integer -# org_id :integer -# plan_id :integer -# created_at :datetime -# updated_at :datetime +# id :integer not null, primary key +# email :string +# name :string +# phone :string +# roles :integer not null +# created_at :datetime +# updated_at :datetime +# org_id :integer +# plan_id :integer not null # # Indexes # -# index_contributors_on_id (id) -# index_contributors_on_email (email) -# index_contributors_on_org_id (org_id) +# index_contrib_id_and_org_id (name,id,org_id) +# index_contributors_on_email (email) +# index_contributors_on_org_id (org_id) +# index_contributors_on_plan_id (plan_id) +# index_contributors_on_roles (roles) # -# Foreign Keys -# -# fk_rails_... (org_id => orgs.id) -# fk_rails_... (plan_id => plans.id) # Object that represents a contributor to a plan class Contributor < ApplicationRecord diff --git a/app/models/identifier.rb b/app/models/identifier.rb index 6ec4ec5bd1..64b0082b7e 100644 --- a/app/models/identifier.rb +++ b/app/models/identifier.rb @@ -11,11 +11,13 @@ # created_at :datetime # updated_at :datetime # identifiable_id :integer -# identifier_scheme_id :integer not null +# identifier_scheme_id :integer # # Indexes # # index_identifiers_on_identifiable_type_and_identifiable_id (identifiable_type,identifiable_id) +# index_identifiers_on_identifier_scheme_id_and_value (identifier_scheme_id,value) +# index_identifiers_on_scheme_and_type_and_id (identifier_scheme_id,identifiable_id,identifiable_type) # # Object that represents an identifier for an object diff --git a/app/models/identifier_scheme.rb b/app/models/identifier_scheme.rb index da664144eb..55ec94f129 100644 --- a/app/models/identifier_scheme.rb +++ b/app/models/identifier_scheme.rb @@ -4,15 +4,16 @@ # # Table name: identifier_schemes # -# id :integer not null, primary key -# active :boolean -# description :string -# context :integer -# logo_url :text -# name :string -# user_landing_url :string -# created_at :datetime -# updated_at :datetime +# id :integer not null, primary key +# active :boolean +# context :integer +# description :string +# external_service :string +# identifier_prefix :string +# logo_url :string +# name :string +# created_at :datetime +# updated_at :datetime # # Object that represents a type of identifiaction (e.g. ORCID, ROR, etc.) diff --git a/app/models/license.rb b/app/models/license.rb index e59f74250d..1668a62010 100644 --- a/app/models/license.rb +++ b/app/models/license.rb @@ -4,7 +4,7 @@ # # Table name: licenses # -# id :bigint not null, primary key +# id :bigint(8) not null, primary key # deprecated :boolean default(FALSE) # identifier :string not null # name :string not null diff --git a/app/models/metadata_standard.rb b/app/models/metadata_standard.rb index 02eaccfd1f..ca546a5255 100644 --- a/app/models/metadata_standard.rb +++ b/app/models/metadata_standard.rb @@ -4,15 +4,15 @@ # # Table name: metadata_standards # -# id :bigint not null, primary key -# description :text -# locations :json -# related_entities :json -# title :string -# uri :string -# created_at :datetime not null -# updated_at :datetime not null -# rdamsc_id :string +# id :bigint(8) not null, primary key +# description :text +# locations :json +# related_entities :json +# title :string +# uri :string +# created_at :datetime not null +# updated_at :datetime not null +# rdamsc_id :string # class MetadataStandard < ApplicationRecord # ============= diff --git a/app/models/notification.rb b/app/models/notification.rb index b26be026f7..3c98da768c 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -7,20 +7,20 @@ # id :integer not null, primary key # body :text # dismissable :boolean +# enabled :boolean default(TRUE) # expires_at :date # level :integer # notification_type :integer # starts_at :date # title :string -# enabled :boolean # created_at :datetime not null # updated_at :datetime not null # # Object that represents a global notification class Notification < ApplicationRecord - enum level: %i[info warning danger] - enum notification_type: %i[global] + enum :level, %i[info warning danger] + enum :notification_type, %i[global] # ================ # = Associations = diff --git a/app/models/org.rb b/app/models/org.rb index 6a6eac55d2..d4d0885bda 100644 --- a/app/models/org.rb +++ b/app/models/org.rb @@ -4,31 +4,37 @@ # # Table name: orgs # -# id :integer not null, primary key -# abbreviation :string -# contact_email :string -# contact_name :string -# feedback_msg :text -# feedback_enabled :boolean default(FALSE) -# is_other :boolean default(FALSE), not null -# links :text -# logo_name :string -# logo_uid :string -# managed :boolean default(FALSE), not null -# name :string -# org_type :integer default(0), not null -# sort_name :string -# target_url :string -# created_at :datetime not null -# updated_at :datetime not null -# language_id :integer -# region_id :integer -# managed :boolean default(false), not null -# helpdesk_email :string +# id :integer not null, primary key +# abbreviation :string +# api_create_plan_email_body :text +# api_create_plan_email_subject :string +# contact_email :string +# contact_name :string +# feedback_enabled :boolean default(FALSE) +# feedback_msg :text +# helpdesk_email :string +# is_other :boolean default(FALSE), not null +# links :text +# logo_name :string +# logo_uid :string +# managed :boolean default(FALSE), not null +# name :string +# org_type :integer default(0), not null +# target_url :string +# created_at :datetime not null +# updated_at :datetime not null +# language_id :integer +# region_id :integer +# +# Indexes +# +# fk_rails_5640112cab (language_id) +# fk_rails_5a6adf6bab (region_id) # # Foreign Keys # # fk_rails_... (language_id => languages.id) +# fk_rails_... (region_id => regions.id) # # Object that represents an Organization/Institution/Funder diff --git a/app/models/plan.rb b/app/models/plan.rb index 83fac933e9..22630c6f20 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -7,39 +7,41 @@ # # Table name: plans # -# id :integer not null, primary key -# complete :boolean default(FALSE) -# description :text -# feedback_requested :boolean default(FALSE) -# identifier :string -# title :string -# visibility :integer default(3), not null -# created_at :datetime -# updated_at :datetime -# template_id :integer -# org_id :integer -# funder_id :integer -# grant_id :integer -# api_client_id :integer -# research_domain_id :bigint -# funding_status :integer -# ethical_issues :boolean -# ethical_issues_description :text -# ethical_issues_report :string +# id :integer not null, primary key +# complete :boolean default(FALSE) +# description :text +# end_date :datetime +# ethical_issues :boolean +# ethical_issues_description :text +# ethical_issues_report :string +# feedback_requested :boolean default(FALSE) +# funding_status :integer +# identifier :string +# start_date :datetime +# title :string +# visibility :integer default(3), not null +# created_at :datetime +# updated_at :datetime +# api_client_id :integer +# funder_id :integer +# grant_id :integer +# org_id :integer +# research_domain_id :bigint(8) +# template_id :integer # # Indexes # -# index_plans_on_template_id (template_id) -# index_plans_on_funder_id (funder_id) -# index_plans_on_grant_id (grant_id) -# index_plans_on_api_client_id (api_client_id) +# index_plans_on_api_client_id (api_client_id) +# index_plans_on_fos_id (research_domain_id) +# index_plans_on_funder_id (funder_id) +# index_plans_on_grant_id (grant_id) +# index_plans_on_org_id (org_id) +# index_plans_on_template_id (template_id) # # Foreign Keys # -# fk_rails_... (template_id => templates.id) # fk_rails_... (org_id => orgs.id) -# fk_rails_... (api_client_id => api_clients.id) -# fk_rails_... (research_domain_id => research_domains.id) +# fk_rails_... (template_id => templates.id) # # Object that represents an DMP @@ -76,10 +78,10 @@ class Plan < ApplicationRecord # ============== # public is a Ruby keyword so using publicly - enum visibility: %i[organisationally_visible publicly_visible - is_test privately_visible] + enum :visibility, %i[organisationally_visible publicly_visible + is_test privately_visible] - enum funding_status: %i[planned funded denied] + enum :funding_status, %i[planned funded denied] alias_attribute :name, :title diff --git a/app/models/question_format.rb b/app/models/question_format.rb index 803e5725f4..5625cef4fc 100644 --- a/app/models/question_format.rb +++ b/app/models/question_format.rb @@ -24,7 +24,7 @@ class QuestionFormat < ApplicationRecord # = Attributes = # ============== - enum formattype: FORMAT_TYPES + enum :formattype, FORMAT_TYPES alias_attribute :to_s, :title diff --git a/app/models/question_option.rb b/app/models/question_option.rb index 9de8fb6451..2c855eb92a 100644 --- a/app/models/question_option.rb +++ b/app/models/question_option.rb @@ -4,17 +4,19 @@ # # Table name: question_options # -# id :integer not null, primary key -# is_default :boolean -# number :integer -# text :string -# created_at :datetime -# updated_at :datetime -# question_id :integer +# id :integer not null, primary key +# is_default :boolean +# number :integer +# text :string +# created_at :datetime +# updated_at :datetime +# question_id :integer +# versionable_id :string(36) # # Indexes # -# index_question_options_on_question_id (question_id) +# index_question_options_on_question_id (question_id) +# index_question_options_on_versionable_id (versionable_id) # # Foreign Keys # diff --git a/app/models/region.rb b/app/models/region.rb index 514671e44d..a191b8db31 100644 --- a/app/models/region.rb +++ b/app/models/region.rb @@ -4,12 +4,11 @@ # # Table name: regions # -# id :integer not null, primary key -# abbreviation :string -# description :string -# name :string not null -# created_at :datetime not null -# updated_at :datetime not null +# id :integer not null, primary key +# abbreviation :string +# description :string +# name :string +# super_region_id :integer # # Object that represents a regional area diff --git a/app/models/repository.rb b/app/models/repository.rb index 344dcb889b..64cb64fea2 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -4,21 +4,21 @@ # # Table name: repositories # -# id :bigint not null, primary key +# id :bigint(8) not null, primary key # contact :string # description :text not null +# homepage :string # info :json # name :string not null -# homepage :string +# uri :string not null # created_at :datetime not null # updated_at :datetime not null -# uri :string not null # # Indexes # -# index_repositories_on_name (name) -# index_repositories_on_homepage (homepage) -# index_repositories_on_uri (uri) +# index_repositories_on_homepage (homepage) +# index_repositories_on_name (name) +# index_repositories_on_uri (uri) # # Object that represents a research output repository (e.g. GitHub or Zenodo) class Repository < ApplicationRecord diff --git a/app/models/research_domain.rb b/app/models/research_domain.rb index 87f8abd4a6..06d4bfb3d7 100644 --- a/app/models/research_domain.rb +++ b/app/models/research_domain.rb @@ -4,12 +4,12 @@ # # Table name: research_domains # -# id :bigint not null, primary key -# identifier :string not null -# label :string not null -# created_at :datetime not null -# updated_at :datetime not null -# parent_id :bigint +# id :bigint(8) not null, primary key +# identifier :string not null +# label :string not null +# created_at :datetime not null +# updated_at :datetime not null +# parent_id :bigint(8) # # Indexes # diff --git a/app/models/research_output.rb b/app/models/research_output.rb index 243b925185..05e684172c 100644 --- a/app/models/research_output.rb +++ b/app/models/research_output.rb @@ -4,14 +4,14 @@ # # Table name: research_outputs # -# id :bigint not null, primary key +# id :bigint(8) not null, primary key # abbreviation :string -# access :integer default("open"), not null -# byte_size :bigint +# access :integer default(0), not null +# byte_size :bigint(8) # description :text # display_order :integer # is_default :boolean -# output_type :integer default("dataset"), not null +# output_type :integer default(3), not null # output_type_description :string # personal_data :boolean # release_date :datetime @@ -19,16 +19,17 @@ # title :string not null # created_at :datetime not null # updated_at :datetime not null -# license_id :bigint +# license_id :bigint(8) # plan_id :integer # # Indexes # +# index_research_outputs_on_license_id (license_id) # index_research_outputs_on_output_type (output_type) +# index_research_outputs_on_plan_id (plan_id) # # Foreign Keys # -# fk_rails_... (plan_id => plans.id) # fk_rails_... (license_id => licenses.id) # @@ -37,11 +38,11 @@ class ResearchOutput < ApplicationRecord include Identifiable include ValidationMessages - enum output_type: %i[audiovisual collection data_paper dataset event image - interactive_resource model_representation physical_object - service software sound text workflow other] + enum :output_type, %i[audiovisual collection data_paper dataset event image + interactive_resource model_representation physical_object + service software sound text workflow other] - enum access: %i[open embargoed restricted closed] + enum :access, %i[open embargoed restricted closed] # ================ # = Associations = diff --git a/app/models/settings/template.rb b/app/models/settings/template.rb index 79b7fb21e2..cf6e450efa 100644 --- a/app/models/settings/template.rb +++ b/app/models/settings/template.rb @@ -5,9 +5,9 @@ # Table name: settings # # id :integer not null, primary key -# target_type :string not null +# target_type :string # value :text -# var :string not null +# var :string # created_at :datetime not null # updated_at :datetime not null # target_id :integer not null diff --git a/app/models/stat_created_plan.rb b/app/models/stat_created_plan.rb index 4c2c7f2c1f..6c2b226bed 100644 --- a/app/models/stat_created_plan.rb +++ b/app/models/stat_created_plan.rb @@ -15,8 +15,6 @@ # org_id :integer # -require 'set' - # Object that represents a Nbr of Plans created usage statistic class StatCreatedPlan < Stat serialize :details, coder: JSON diff --git a/app/models/template.rb b/app/models/template.rb index cf4d547510..d99697dcef 100644 --- a/app/models/template.rb +++ b/app/models/template.rb @@ -44,7 +44,7 @@ class Template < ApplicationRecord # that are meant for external use will be publicly visible. This allows a # funder to create 'funder' as well as organisational templates. The default # template should also always be publicly_visible. - enum visibility: %i[organisationally_visible publicly_visible] + enum :visibility, %i[organisationally_visible publicly_visible] # Stores links as an JSON object: # {funder: [{"link":"www.example.com","text":"foo"}, ...], diff --git a/app/models/tracker.rb b/app/models/tracker.rb index 7e62838d12..6acdd5b781 100644 --- a/app/models/tracker.rb +++ b/app/models/tracker.rb @@ -1,6 +1,24 @@ # frozen_string_literal: true # Object that represents a Google Analytics tracker code +# == Schema Information +# +# Table name: trackers +# +# id :integer not null, primary key +# code :string +# created_at :datetime not null +# updated_at :datetime not null +# org_id :integer +# +# Indexes +# +# index_trackers_on_org_id (org_id) +# +# Foreign Keys +# +# fk_rails_... (org_id => orgs.id) +# class Tracker < ApplicationRecord belongs_to :org validates :code, format: { with: /\A\z|\AUA-[0-9]+-[0-9]+\z/, diff --git a/app/models/user.rb b/app/models/user.rb index 94d0035eec..389a81d306 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -21,9 +21,12 @@ # invitation_sent_at :datetime # invitation_token :string # invited_by_type :string +# last_api_access :datetime # last_sign_in_at :datetime # last_sign_in_ip :string -# other_organisation :string +# ldap_password :string +# ldap_username :string +# other_organisation :string # recovery_email :string # remember_created_at :datetime # reset_password_sent_at :datetime diff --git a/app/views/devise/invitations/edit.html.erb b/app/views/devise/invitations/edit.html.erb index 744c37e8e3..488286afa9 100644 --- a/app/views/devise/invitations/edit.html.erb +++ b/app/views/devise/invitations/edit.html.erb @@ -9,7 +9,7 @@
Noo bar
' } end + expect(Annotation.uncached { Annotation.count }).to eq(annotation_count) expect(annotation.text).to eql('Foo bar') - expect(Annotation.order('created_at').last.text).to eql('Noo bar
') + expect(Annotation.uncached { Annotation.find(copied_annotation_id).text }).to eql('Noo bar
') expect(page).not_to have_errors end @@ -65,22 +71,27 @@ within("#template_#{template.id}") do click_button 'Actions' end - expect do - click_link 'Customise' - end.to change { Template.count }.by(1) + template_count = Template.count + click_link 'Customise' + expect(page).to have_current_path(%r{\A/org_admin/templates/\d+\z}) + expect(Template.count).to eq(template_count + 1) template = Template.last click_link 'Customise phase' click_link section.title # NOTE: This is annotation 2, since Annotation was copied upon clicking "Customise" - within("fieldset#fields_annotation_#{template.annotation_ids.last}") do - id = "question_annotations_attributes_annotation_#{template.annotation_ids.last}_text" + copied_annotation_id = template.annotation_ids.last + within("fieldset#fields_annotation_#{copied_annotation_id}") do + id = "question_annotations_attributes_annotation_#{copied_annotation_id}_text" tinymce_fill_in(:"#{id}", with: ' ') end # NOTE: This is question 2, since Annotation was copied upon clicking "Customise" - within("#edit_question_#{template.question_ids.last}") do - # Expect it to destroy the newly cleared Annotation - expect { click_button 'Save' }.to change { Annotation.count }.by(-1) + annotation_count = Annotation.count + question_id = template.question_ids.last + within("#edit_question_#{question_id}") { click_button 'Save' } + Timeout.timeout(Capybara.default_max_wait_time) do + sleep 0.05 while Annotation.uncached { Annotation.exists?(copied_annotation_id) } end + expect(Annotation.uncached { Annotation.count }).to eq(annotation_count - 1) expect(page).not_to have_errors end end diff --git a/spec/features/feedback_requests_spec.rb b/spec/features/feedback_requests_spec.rb index 4d6eaccfdf..edfafbaebf 100644 --- a/spec/features/feedback_requests_spec.rb +++ b/spec/features/feedback_requests_spec.rb @@ -40,6 +40,7 @@ end # Expectations + expect(page).to have_text('Feedback has been requested.') expect(plan.reload).to be_feedback_requested expect(ActionMailer::Base.deliveries).to have_exactly(1).item end diff --git a/spec/features/modal_search_spec.rb b/spec/features/modal_search_spec.rb index c2b3f990bc..1eed171760 100644 --- a/spec/features/modal_search_spec.rb +++ b/spec/features/modal_search_spec.rb @@ -63,7 +63,7 @@ def perform_modal_actions close_modal end # Verify that the selection was added to the main page's dom - expect(page).not_to have_text('Repository search') + expect(page).to have_no_css('#modal-search-repositories', visible: true) expect(page).to have_text(@model.description) end @@ -84,9 +84,6 @@ def search_and_select_repository_within_modal end def close_modal - # Using JS to click on button, as click_button '.modal-header button.btn-close' did not work. - modal_close_button = find('.modal-header button.btn-close') - # Close the modal - execute_script('arguments[0].click();', modal_close_button) + find('.modal-header button.btn-close').click end end diff --git a/spec/features/plans_spec.rb b/spec/features/plans_spec.rb index eb7ba84a43..ab3c03ad85 100644 --- a/spec/features/plans_spec.rb +++ b/spec/features/plans_spec.rb @@ -45,10 +45,10 @@ click_button 'Create plan' # Expectations + expect(page).to have_css("input[type=text][value='My test plan']") expect(@user.plans).to be_one @plan = Plan.last - expect(current_path).to eql(plan_path(@plan)) - expect(page).to have_css("input[type=text][value='#{@plan.title}']") + expect(page).to have_current_path(plan_path(@plan)) expect(@plan.title).to eql('My test plan') expect(@plan.org_id).to eql(@research_org.id) expect(@plan.funder_id).to eql(@funding_org.id) diff --git a/spec/features/questions/dropdown_questions_spec.rb b/spec/features/questions/dropdown_questions_spec.rb index f157dd4621..9f252da43b 100644 --- a/spec/features/questions/dropdown_questions_spec.rb +++ b/spec/features/questions/dropdown_questions_spec.rb @@ -24,7 +24,7 @@ click_link 'Write plan' # Expectations - expect(current_path).to eql(edit_plan_path(@plan)) + expect(page).to have_current_path(edit_plan_path(@plan), ignore_query: true) # 4 sections x 3 questions expect(page).to have_text('(0 / 1)') diff --git a/spec/features/questions/textarea_questions_spec.rb b/spec/features/questions/textarea_questions_spec.rb index 34e3fcf84c..37b32e711e 100644 --- a/spec/features/questions/textarea_questions_spec.rb +++ b/spec/features/questions/textarea_questions_spec.rb @@ -24,7 +24,7 @@ click_link 'Write plan' # Expectations - expect(current_path).to eql(edit_plan_path(@plan)) + expect(page).to have_current_path(edit_plan_path(@plan), ignore_query: true) # 4 sections x 3 questions expect(page).to have_text('(0 / 1)') diff --git a/spec/features/questions/textfield_questions_spec.rb b/spec/features/questions/textfield_questions_spec.rb index 7df6366f37..2b72e2e140 100644 --- a/spec/features/questions/textfield_questions_spec.rb +++ b/spec/features/questions/textfield_questions_spec.rb @@ -24,7 +24,7 @@ click_link 'Write plan' # Expectations - expect(current_path).to eql(edit_plan_path(@plan)) + expect(page).to have_current_path(edit_plan_path(@plan), ignore_query: true) # 4 sections x 3 questions expect(page).to have_text('(0 / 1)') diff --git a/spec/features/registrations_spec.rb b/spec/features/registrations_spec.rb index 50ef4d60ab..b00b93b793 100644 --- a/spec/features/registrations_spec.rb +++ b/spec/features/registrations_spec.rb @@ -26,7 +26,7 @@ click_button 'Create account' # Expectations - expect(current_path).to eql(plans_path) + expect(page).to have_current_path(plans_path) expect(page).to have_text(user_attributes[:firstname]) expect(page).to have_text(user_attributes[:surname]) end @@ -49,7 +49,7 @@ click_button 'Create account' # Expectations - expect(current_path).to eql(root_path) + expect(page).to have_current_path(root_path) expect(User.count).to be_zero end end diff --git a/spec/features/sessions_spec.rb b/spec/features/sessions_spec.rb index 9fb3d7682e..d96c192ec9 100644 --- a/spec/features/sessions_spec.rb +++ b/spec/features/sessions_spec.rb @@ -15,7 +15,7 @@ click_button 'Sign in' # Expectation - expect(current_path).to eql(plans_path) + expect(page).to have_current_path(plans_path) expect(page).to have_text(user.firstname) expect(page).to have_text(user.surname) end @@ -30,7 +30,7 @@ click_button 'Sign in' # Expectation - expect(current_path).to eql(root_path) + expect(page).to have_current_path(root_path) expect(page).not_to have_text(user.firstname) expect(page).not_to have_text(user.surname) expect(page).to have_text('Error') diff --git a/spec/features/templates/templates_copying_spec.rb b/spec/features/templates/templates_copying_spec.rb index 6910c47c5d..025389395e 100644 --- a/spec/features/templates/templates_copying_spec.rb +++ b/spec/features/templates/templates_copying_spec.rb @@ -34,6 +34,7 @@ end # Expectations + expect(page).to have_current_path(%r{\A/org_admin/templates/\d+/edit\z}) expect(Template.count).to eql(2) new_template = Template.last expect(new_template.title).to include(parent_template.title) diff --git a/spec/features/templates/templates_editings_spec.rb b/spec/features/templates/templates_editings_spec.rb index a56237f880..7a299a3dc6 100644 --- a/spec/features/templates/templates_editings_spec.rb +++ b/spec/features/templates/templates_editings_spec.rb @@ -30,6 +30,7 @@ click_button 'Actions' end click_link 'Customise' + expect(page).to have_current_path(%r{\A/org_admin/templates/\d+\z}) # New template created template = Template.last within("#phase_#{template.phase_ids.first}") do diff --git a/spec/features/templates/templates_upgrade_customisations_spec.rb b/spec/features/templates/templates_upgrade_customisations_spec.rb index 715691b69c..517feef0e6 100644 --- a/spec/features/templates/templates_upgrade_customisations_spec.rb +++ b/spec/features/templates/templates_upgrade_customisations_spec.rb @@ -36,7 +36,10 @@ click_link('Customisable Templates') click_button 'Actions' - expect { click_link 'Customise' }.to change { Template.count }.by(1) + template_count = Template.count + click_link 'Customise' + expect(page).to have_current_path(%r{\A/org_admin/templates/\d+\z}) + expect(Template.count).to eq(template_count + 1) customized_template = Template.last @@ -48,6 +51,7 @@ # Publish our customisation click_button 'Actions' click_link 'Publish' + expect(page).to have_css("#template_#{funder_template.id} td:nth-child(3)", text: 'Published') expect(customized_template.reload.published?).to eql(true) # Move to the other funder Org's Templates @@ -64,11 +68,14 @@ click_link(funder_template.phases.first.title) click_link 'Add a new section' + section_count = Section.count within('#new_section_new_section') do fill_in :new_section_section_title, with: 'Cool New section title' tinymce_fill_in :new_section_section_description, with: 'New section Description' - expect { click_button('Save') }.to change { Section.count }.by(3) + click_button 'Save' end + expect(page).to have_no_css('#new_section_new_section') + expect(Section.count).to eq(section_count + 3) within("#section-#{Section.last.id}") do within('.new-question-button') do @@ -76,10 +83,13 @@ end expect(page).to have_selector('#new_question_new_question') + question_count = Question.count within('#new_question_new_question') do tinymce_fill_in :new_question_question_text, with: 'Text for this specific question' - expect { click_button('Save') }.to change { Question.count }.by(1) + click_button 'Save' end + expect(page).to have_no_css('#new_question_new_question') + expect(Question.count).to eq(question_count + 1) end new_funder_template = Template.last @@ -88,6 +98,7 @@ click_button 'Actions' click_link 'Publish changes' + expect(page).to have_text('has been published and is now available to users.') expect(new_funder_template.reload.published?).to eql(true) # Go back to the original Org... diff --git a/spec/javascripts/autoCompleteSpec.js b/spec/javascripts/autoCompleteSpec.js index 552d3f9735..ed30ced8d1 100644 --- a/spec/javascripts/autoCompleteSpec.js +++ b/spec/javascripts/autoCompleteSpec.js @@ -1,19 +1,21 @@ -import initAutoComplete from '../../app/javascript/src/utils/autoComplete'; +import { initAutocomplete } from '../../app/javascript/src/utils/autoComplete'; -describe('autoComplete test suite', () => { - beforeAll(() => fixture.setBase('./spec/javascripts/fixtures')); +describe('autocomplete', () => { + afterEach(() => $('body').empty()); - beforeEach(() => { - $('body').html(fixture.load('autoComplete.html')); - initAutoComplete(); - // Override the form submission, we are just going to validate the ariatisation of the form - $('form').trigger('submit', (e) => { e.preventDefault(); }); - }); + it('keeps the selected organisation record in the hidden field', () => { + $('body').append(` + + `); - // TODO : Needs fixing, tests need to have at least one it() in a describe() + initAutocomplete('#org_name'); - afterEach(() => { - fixture.cleanup(); - $('body').html(''); + expect($('.autocomplete-result').val()).toBe('{"name":"Example University","id":42}'); }); }); diff --git a/spec/javascripts/tinymceSpec.js b/spec/javascripts/tinymceSpec.js index ad92ca6ab5..e31a9d5f1e 100644 --- a/spec/javascripts/tinymceSpec.js +++ b/spec/javascripts/tinymceSpec.js @@ -1,4 +1,4 @@ -import { Tinymce } from '../../app/javascript/src/utils/tinymce.js.erb'; +import { Tinymce } from '../../app/javascript/src/utils/tinymce'; beforeEach(() => { $('body').append(''); diff --git a/spec/models/flag_shih_tzu_compatibility_spec.rb b/spec/models/flag_shih_tzu_compatibility_spec.rb new file mode 100644 index 0000000000..799308324f --- /dev/null +++ b/spec/models/flag_shih_tzu_compatibility_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'FlagShihTzu stored values', type: :model do + it 'selects organisation types from the same stored bits' do + org = create(:org, org_type: 3) + + expect(org).to be_institution + expect(org).to be_funder + expect(Org.institution).to include(org) + expect(Org.funder).to include(org) + expect(Org.school).not_to include(org) + end + + it 'selects plan access from the same stored bits' do + role = create(:role, access: 5) + + expect(role).to be_creator + expect(role).to be_editor + expect(Role.creator).to include(role) + expect(Role.editor).to include(role) + expect(Role.reviewer).not_to include(role) + end + + it 'selects contributor roles from the same stored bits' do + contributor = create(:contributor, plan: create(:plan), roles: 3, roles_count: 0) + + expect(contributor).to be_data_curation + expect(contributor).to be_investigation + expect(Contributor.data_curation).to include(contributor) + expect(Contributor.investigation).to include(contributor) + expect(Contributor.other).not_to include(contributor) + end +end diff --git a/spec/requests/api/v1/templates_controller_spec.rb b/spec/requests/api/v1/templates_controller_spec.rb index 3cb6f5d427..61e654e7fb 100644 --- a/spec/requests/api/v1/templates_controller_spec.rb +++ b/spec/requests/api/v1/templates_controller_spec.rb @@ -11,6 +11,14 @@ end describe 'GET /api/v1/templates - index' do + it 'keeps the existing pagination header contract' do + create_list(:template, 2, :publicly_visible, :published, customization_of: nil) + get api_v1_templates_path, params: { per_page: 1 } + + expect(response).to have_http_status(:ok) + expect(response.headers.keys).not_to include('Link', 'X-Total', 'X-Per-Page') + end + it 'returns a even if there are no public templates' do get api_v1_templates_path expect(response.code).to eql('200') diff --git a/spec/requests/devise_5_views_spec.rb b/spec/requests/devise_5_views_spec.rb new file mode 100644 index 0000000000..9e5beb9b92 --- /dev/null +++ b/spec/requests/devise_5_views_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Devise 5 views', type: :request do + it 'renders the password reset form with the supported error partial' do + get edit_user_password_path, params: { reset_password_token: 'invalid' } + + expect(response).to have_http_status(:ok) + expect(response.body).to include('user_reset_password_form') + end + + it 'renders an invitation acceptance form with devise_invitable' do + invited_user = User.invite!({ email: 'invited@example.org' }, create(:user)) + + get accept_user_invitation_path, params: { invitation_token: invited_user.raw_invitation_token } + + expect(response).to have_http_status(:ok) + expect(response.body).to include('invitation_create_account_form') + end +end diff --git a/spec/requests/plan_docx_export_spec.rb b/spec/requests/plan_docx_export_spec.rb new file mode 100644 index 0000000000..4f99f1e757 --- /dev/null +++ b/spec/requests/plan_docx_export_spec.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'rails_helper' +require 'zip' + +RSpec.describe 'Plan DOCX export', type: :request do + it 'returns a readable Word document with the plan title' do + template = create(:template, phases: 1) + phase = template.phases.first + section = create(:section, phase: phase) + create(:question, section: section) + plan = create(:plan, :publicly_visible, template: template, title: 'Rubyzip compatibility plan') + + get plan_export_path(plan, format: :docx), params: { export: { question_headings: '1' } } + + expect(response).to have_http_status(:ok) + Zip::File.open_buffer(response.body) do |archive| + document = Nokogiri::XML(archive.read('word/document.xml')) + expect(document.text).to include(plan.title, 'Plan Overview') + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2904a6894d..28ca1b3921 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -98,14 +98,17 @@ # Capture the current time so that we can compare against files afterward # to clear out any downloaded/exported plans/templates @start_time = Time.now + @existing_export_files = Dir.glob(Rails.root.join('*.{csv,txt,docx,pdf}').to_s) end config.after(:context) do # Clean up any files generated by the Export/Download UI pages path = Rails.root.join('*.{csv,txt,docx,pdf}').to_s Dir.glob(path).each do |file| + next if @existing_export_files.include?(file) || File.ctime(file) <= @start_time + puts "Deleting test file generated by Download/Export: #{file}" - File.delete(file) if File.ctime(file) > @start_time + File.delete(file) end end diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb index c6e8ee618c..e398a29b47 100644 --- a/spec/support/capybara.rb +++ b/spec/support/capybara.rb @@ -11,6 +11,7 @@ options.add_argument('--window-size=1920,1080') options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage') + options.binary = ENV['CHROME_BIN'] if ENV['CHROME_BIN'] # Create a new Selenium driver with the customised options Capybara::Selenium::Driver.new(app, browser: :chrome, options: options) end diff --git a/spec/support/helpers/sessions_helper.rb b/spec/support/helpers/sessions_helper.rb index 3fa530d4e9..339e1f27fd 100644 --- a/spec/support/helpers/sessions_helper.rb +++ b/spec/support/helpers/sessions_helper.rb @@ -20,5 +20,6 @@ def sign_in_as_user(user) fill_in 'Password', with: user.password.presence || 'password' click_button 'Sign in' end + expect(page).to have_css("a[href='#{destroy_user_session_path}']", visible: :all) end end diff --git a/yarn.lock b/yarn.lock index ec52161252..9f5646f477 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1494,6 +1494,13 @@ babel-loader@^9.1.2: find-cache-dir "^4.0.0" schema-utils "^4.0.0" +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + babel-plugin-macros@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" @@ -3373,7 +3380,7 @@ object-keys@^1.1.1: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.2, object.assign@^4.1.7: +object.assign@^4.1.0, object.assign@^4.1.2, object.assign@^4.1.7: version "4.1.7" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==