diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1cf2c53c..9f6292c3b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: Test on: push: branches: - - master + - main paths-ignore: - '**.md' pull_request: @@ -27,10 +27,12 @@ jobs: fail-fast: false matrix: ruby: - - 3.0.2 - - 2.7.4 - - 2.6.8 + - 3.1.2 + - 3.0.4 + - 2.7.6 + - 2.6.10 appraisal: + - rails_7_0 - rails_6_1 - rails_6_0 - rails_5_2 @@ -38,7 +40,11 @@ jobs: - sqlite3 - postgresql exclude: - - { ruby: 3.0.2, appraisal: rails_5_2 } + - { ruby: 3.1.2, appraisal: rails_5_2 } + - { ruby: 3.0.4, appraisal: rails_5_2 } + - { ruby: 3.0.4, appraisal: rails_7_0 } + - { ruby: 2.7.6, appraisal: rails_7_0 } + - { ruby: 2.6.10, appraisal: rails_7_0 } env: DATABASE_ADAPTER: ${{ matrix.adapter }} BUNDLE_GEMFILE: gemfiles/${{ matrix.appraisal }}.gemfile diff --git a/.rubocop.yml b/.rubocop.yml index 173e6376c..add6007a3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -30,7 +30,7 @@ Layout/LineLength: - '^[ ]*#.+$' - '^[ ]*''.+?'' => ''.+?'',?$' - '^[ ]*".+?" => ".+?",?$' - Max: 80 + Max: 100 Layout/MultilineMethodCallIndentation: EnforcedStyle: indented Layout/ParameterAlignment: @@ -104,6 +104,8 @@ Naming/MemoizedInstanceVariableName: EnforcedStyleForLeadingUnderscores: required Naming/PredicateName: Enabled: false +Naming/VariableNumber: + Enabled: false Naming/RescuedExceptionsVariableName: Enabled: false Rails/Date: diff --git a/.ruby-version b/.ruby-version index b50214693..ef538c281 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.0.2 +3.1.2 diff --git a/.tool-versions b/.tool-versions index a2e778299..0b2d85878 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -ruby 3.0.2 +ruby 3.1.2 diff --git a/Appraisals b/Appraisals index ac5bf2d43..9cfb8bacf 100644 --- a/Appraisals +++ b/Appraisals @@ -27,7 +27,7 @@ appraise 'rails_5_2' do instance_eval(&shared_dependencies) instance_eval(&controller_test_dependency) - gem 'rails', '5.2.6' + gem 'rails', '5.2.8.1' gem 'puma', '~> 3.11' gem 'bootsnap', '>= 1.1.0', require: false gem 'sass-rails', '~> 5.0' @@ -42,14 +42,14 @@ appraise 'rails_5_2' do # Database adapters gem 'pg', '~> 0.18' - gem 'sqlite3', '~> 1.3.6' + gem 'sqlite3', '~> 1.4' end appraise 'rails_6_0' do instance_eval(&shared_dependencies) instance_eval(&controller_test_dependency) - gem 'rails', '6.0.4' + gem 'rails', '6.0.6' gem 'puma', '~> 4.1' gem 'bootsnap', '>= 1.4.2', require: false gem 'sass-rails', '>= 6' @@ -58,12 +58,11 @@ appraise 'rails_6_0' do gem 'bcrypt', '~> 3.1.7' gem 'capybara', '>= 2.15' gem 'listen', '~> 3.3.0' + gem 'psych', '~> 3.0' gem 'spring-watcher-listen', '~> 2.0.0' gem 'selenium-webdriver' gem 'webdrivers' - - # Other dependencies - gem 'actiontext', '~> 6.0.4' + gem 'net-smtp', require: false # Database adapters gem 'pg', '>= 0.18', '< 2.0' @@ -74,7 +73,7 @@ appraise 'rails_6_1' do instance_eval(&shared_dependencies) instance_eval(&controller_test_dependency) - gem 'rails', '6.1.4' + gem 'rails', '6.1.7' gem 'puma', '~> 5.0' gem 'bootsnap', '>= 1.4.2', require: false gem 'sass-rails', '>= 6' @@ -83,15 +82,41 @@ appraise 'rails_6_1' do gem 'bcrypt', '~> 3.1.7' gem 'capybara', '>= 2.15' gem 'listen', '>= 3.0.5', '< 3.6' + gem 'net-smtp', require: false + gem 'psych', '~> 3.0' gem 'rack-mini-profiler', '~> 2.0.0' gem 'spring-watcher-listen', '~> 2.0.0' gem 'selenium-webdriver' gem 'webdrivers' - # Other dependencies - gem 'actiontext', '~> 6.1.4' - # Database adapters gem 'pg', '>= 0.18', '< 2.0' gem 'sqlite3', '~> 1.4' end + +appraise 'rails_7_0' do + instance_eval(&shared_spring_dependencies) + instance_eval(&shared_test_dependencies) + + gem 'rails', '~> 7.0.1' + gem 'sprockets-rails' + gem 'puma', '~> 5.0' + gem 'importmap-rails' + gem 'turbo-rails' + gem 'stimulus-rails' + gem 'jbuilder' + gem 'redis', '~> 4.0' + gem 'bootsnap', require: false + gem 'capybara' + gem 'selenium-webdriver' + gem 'webdrivers' + + # other dependencies + gem 'bcrypt', '~> 3.1.7' + gem 'rails-controller-testing' + gem 'debug', platforms: %i[mri mingw x64_mingw] + + # Database adapters + gem 'sqlite3', '~> 1.4' + gem 'pg', '~> 1.1' +end diff --git a/CHANGELOG.md b/CHANGELOG.md index 84336c2e7..f1710b421 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,57 @@ # Changelog +## 5.3.0 - 2022-12-16 + +### Features + +* Add `in: range` matcher to validate_numericality_of. ([#1512]) + +* Support :uuid column type for validate_absence_of matcher. ([#1518]) + +[#1512]: https://github.com/thoughtbot/shoulda-matchers/pull/1512 +[#1518]: https://github.com/thoughtbot/shoulda-matchers/pull/1518 + +### Bug fixes + +* Fix confusing error message from validate_inclusion_of matcher when used against a polymorphic association. ([#1523]) + +[#1523]: https://github.com/thoughtbot/shoulda-matchers/pull/1523 + +## 5.2.0 - 2022-09-15 + +### Features + +* Add without_scopes method to enum matcher. ([#1453]) + +* Add support for Ruby 3.1. ([#1474]) + +* Add allow_blank method to validate_presence_of matcher. ([#1499]) + +* Add support for Rails 7.0. No new Rails 7.0 features are supported, but only + existing features that broke with the upgrade. ([#1506]) + +[#1453]: https://github.com/thoughtbot/shoulda-matchers/pull/1453 +[#1474]: https://github.com/thoughtbot/shoulda-matchers/pull/1474 +[#1499]: https://github.com/thoughtbot/shoulda-matchers/pull/1499 +[#1506]: https://github.com/thoughtbot/shoulda-matchers/pull/1506 + +## 5.1.0 - 2021-12-22 + +### Bug fixes + +* Fix the undefined method error for non rails project due to use of many? - method from ActiveSupport. ([#1459]) + +[#1459]: https://github.com/thoughtbot/shoulda-matchers/pull/1459 + +### Features + +* Add array option support for have db column matcher. ([#1465]) + +* Add enum attributes support for validate_absence_of matcher. ([#1464]) + +[#1464]: https://github.com/thoughtbot/shoulda-matchers/pull/1464 +[#1465]: https://github.com/thoughtbot/shoulda-matchers/pull/1465 + ## 5.0.0 - 2021-07-09 ### Bug fixes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 578d57887..90977ee85 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,15 +20,15 @@ you think would be useful? Here's what you need to do: API](#documentation). 1. [Refrain from updating the changelog.](#a-word-on-the-changelog) 1. Push to your fork and submit a pull request. -1. [Ensure that the test suite passes on Travis and make any necessary changes - to your branch to bring it to green.](#continuous-integration) +1. [Ensure that the test suite passes on GitHub Actions and make any necessary + changes to your branch to bring it to green.](#continuous-integration) Although we maintain Shoulda Matchers in our free time, we try to respond to contributions in a timely manner. Once we look at your pull request, we may give you feedback. For instance, we may suggest some changes to make to your code to fit within the project style or discuss alternate ways of addressing the issue in question. Assuming we're happy with everything, we'll then bring your changes -into master. Now you're a contributor! +into main. Now you're a contributor! --- @@ -171,7 +171,7 @@ bundle exec rake guide] was a wonderful piece on this topic when it came out and we still find it to be helpful even today. * Squash "WIP" commits and remove merge commits by rebasing your branch against - `master`. We try to keep our commit history as clean as possible. + `main`. We try to keep our commit history as clean as possible. [Tim Pope's guide]: https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html @@ -199,16 +199,17 @@ your branch, but don't worry about this — we'll take care of it! While running `bundle exec rake` is a great way to check your work, this command will only run your tests against the latest supported Ruby and Rails version. Ultimately, though, you'll want to ensure that your changes work in all possible -environments. We make use of [Travis][travis] to do this work for us. Travis -will kick in after you push up a branch or open a PR. It takes 20-30 minutes to -run a complete build, which you are free to -[monitor as it progresses][shoulda-matchers-on-travis]. +environments. We make use of [GitHub Actions][gh-actions] to do this work for +us. GitHub Actions will kick in after you push up a branch or open a PR. +It takes 20-30 minutes to run a complete build, which you are free to +[monitor as it progresses][shoulda-matchers-on-gh-actions]. First-time +contributors may need to wait until a maintainer approves the build. -[shoulda-matchers-on-travis]: https://travis-ci.org/thoughtbot/shoulda-matchers +[shoulda-matchers-on-gh-actions]: https://github.com/thoughtbot/shoulda-matchers/actions What happens if the build fails in some way? Don't fear! Click on a failed job and scroll through its output to determine the cause of the failure. You'll want to make changes to your branch and push them up until the entire build is green. It may take a bit of time, but overall it is worth it and it helps us immensely! -[travis]: https://travis-ci.org/ +[gh-actions]: https://github.com/features/actions diff --git a/Gemfile b/Gemfile index 879359bad..b618ba19e 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source 'https://rubygems.org' gem 'appraisal', '2.2.0' -gem 'bundler', '~> 1.1' +gem 'bundler', '~> 2.0' gem 'pry' gem 'pry-byebug' gem 'rake', '13.0.1' diff --git a/Gemfile.lock b/Gemfile.lock index 5364786e0..61ee41789 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,28 +1,28 @@ GEM remote: https://rubygems.org/ specs: - activesupport (6.0.3.4) + activesupport (7.0.4) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) appraisal (2.2.0) bundler rake thor (>= 0.14.0) - ast (2.4.1) + ast (2.4.2) byebug (11.1.3) coderay (1.1.3) - concurrent-ruby (1.1.7) + concurrent-ruby (1.1.10) diff-lcs (1.3) fssm (0.2.10) - i18n (1.8.5) + i18n (1.12.0) concurrent-ruby (~> 1.0) + json (2.6.2) method_source (1.0.0) - minitest (5.14.2) - parallel (1.19.2) - parser (2.7.2.0) + minitest (5.16.3) + parallel (1.22.1) + parser (3.1.2.1) ast (~> 2.4.1) pry (0.13.1) coderay (~> 1.1) @@ -30,12 +30,12 @@ GEM pry-byebug (3.9.0) byebug (~> 11.0) pry (~> 0.13.0) - rack (2.2.3) - rainbow (3.0.0) + rack (3.0.0) + rainbow (3.1.1) rake (13.0.1) redcarpet (3.5.0) - regexp_parser (1.8.2) - rexml (3.2.4) + regexp_parser (2.5.0) + rexml (3.2.5) rouge (3.22.0) rspec (3.9.0) rspec-core (~> 3.9.0) @@ -50,32 +50,31 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.9.0) rspec-support (3.9.0) - rubocop (1.0.0) + rubocop (1.36.0) + json (~> 2.3) parallel (~> 1.10) - parser (>= 2.7.1.5) + parser (>= 3.1.2.1) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8) - rexml - rubocop-ast (>= 0.6.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.20.1, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (1.1.0) - parser (>= 2.7.1.5) - rubocop-packaging (0.5.1) - rubocop (>= 0.89, < 2.0) - rubocop-rails (2.8.1) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.21.0) + parser (>= 3.1.1.0) + rubocop-packaging (0.5.2) + rubocop (>= 1.33, < 2.0) + rubocop-rails (2.16.1) activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 0.87.0) - ruby-progressbar (1.10.1) + rubocop (>= 1.33.0, < 2.0) + ruby-progressbar (1.11.0) thor (0.20.0) - thread_safe (0.3.6) - tzinfo (1.2.7) - thread_safe (~> 0.1) - unicode-display_width (1.7.0) + tzinfo (2.0.5) + concurrent-ruby (~> 1.0) + unicode-display_width (2.3.0) warnings_logger (0.1.1) yard (0.9.25) - zeitwerk (2.4.0) zeus (0.15.14) method_source (>= 0.6.7) @@ -84,7 +83,7 @@ PLATFORMS DEPENDENCIES appraisal (= 2.2.0) - bundler (~> 1.1) + bundler (~> 2.0) fssm pry pry-byebug @@ -100,4 +99,4 @@ DEPENDENCIES zeus BUNDLED WITH - 1.17.3 + 2.2.32 diff --git a/LICENSE b/LICENSE index d74be1034..3df646925 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2006-2021 Tammer Saleh and thoughtbot, inc. +Copyright (c) 2006-2023 Tammer Saleh and thoughtbot, inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation diff --git a/MAINTAINING.md b/MAINTAINING.md index 564cc01c9..eddc2fdb8 100644 --- a/MAINTAINING.md +++ b/MAINTAINING.md @@ -48,7 +48,7 @@ patrons happy. We do this by: ## Workflow -We generally follow [GitHub Flow]. The `master` branch is the main line, and all +We generally follow [GitHub Flow]. The `main` branch is the main line, and all branches are cut from and get merged back into this branch. Generally, the workflow is as follows: @@ -154,7 +154,7 @@ That's it! ## Updating the changelog -After every user-facing change makes it into master, we make a note of it in the +After every user-facing change makes it into main, we make a note of it in the changelog, kept in `CHANGELOG.md`. The changelog is sorted in reverse order by release version, with the topmost version as the next release (tagged as "(Unreleased)"). diff --git a/README.md b/README.md index 317b5d2c3..4416addad 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ complex, and error-prone. ## Quick links -📖 **[Read the documentation for the latest version][rubydocs].** +📖 **[Read the documentation for the latest version][rubydocs].** 📢 **[See what's changed in recent versions][changelog].** [rubydocs]: https://matchers.shoulda.io/docs @@ -117,7 +117,7 @@ Otherwise, add `shoulda-matchers` to your Gemfile: ```ruby group :test do - gem 'shoulda-matchers', '~> 4.0' + gem 'shoulda-matchers', '~> 5.0' end ``` @@ -492,7 +492,7 @@ Albuk][guialbuk]. ## Copyright/License -Shoulda Matchers is copyright © 2006-2021 Tammer Saleh and [thoughtbot, +Shoulda Matchers is copyright © 2006-2023 Tammer Saleh and [thoughtbot, inc][thoughtbot-website]. It is free and opensource software and may be redistributed under the terms specified in the [LICENSE](LICENSE) file. diff --git a/bin/setup b/bin/setup index cce91620f..7863271f7 100755 --- a/bin/setup +++ b/bin/setup @@ -8,8 +8,6 @@ set -euo pipefail # section. You may also delete this section altogether if your project doesn't # need a custom setup. -USE_BUNDLER_1=1 - provision-project() { banner "Installing Appraisals" bundle exec appraisal install @@ -187,8 +185,6 @@ setup() { # --- RUBY --------------------------------------------------------------------- provision-ruby() { - USE_BUNDLER_1=0 - if [[ -f .tool-versions ]]; then REQUIRED_RUBY_VERSION=$(cat .tool-versions | grep '^ruby ' | head -n 1 | sed -Ee 's/^ruby (.+)$/\1/') elif [[ -f .ruby-version ]]; then @@ -232,7 +228,18 @@ ensure-ruby-installed() { rbenv install --skip-existing "$REQUIRED_RUBY_VERSION" fi elif has-executable chruby-exec; then - PREFIX='' source /usr/local/share/chruby/chruby.sh + if [ -f /usr/local/share/chruby/chruby.sh ]; then + CHRUBY_SH=/usr/local/share/chruby/chruby.sh + elif [ -f /opt/homebrew/share/chruby/chruby.sh ]; then + CHRUBY_SH=/opt/homebrew/share/chruby/chruby.sh + fi + + if [ -z "$CHRUBY_SH" ]; then + error "chruby-exec detected, but could not find chruby.sh for loading" + exit 1 + fi + + PREFIX='' source $CHRUBY_SH if ! (chruby '' | grep $REQUIRED_RUBY_VERSION'\>' &>/dev/null); then if has-executable install-ruby; then banner "Installing Ruby $REQUIRED_RUBY_VERSION with install-ruby" @@ -265,11 +272,7 @@ has-bundler() { ensure-project-ruby-dependencies-installed() { banner 'Installing Ruby dependencies' - if [[ $USE_BUNDLER_1 -eq 1 ]] && (! has-bundler || ! [[ $(bundle -v) =~ '^Bundler version 1\.' ]]); then - gem install bundler:'~> 1.0' - elif ! has-bundler; then - gem install bundler - fi + gem install bundler bundle check || bundle install } diff --git a/gemfiles/rails_5_2.gemfile b/gemfiles/rails_5_2.gemfile index d162dcbe4..c88b7218e 100644 --- a/gemfiles/rails_5_2.gemfile +++ b/gemfiles/rails_5_2.gemfile @@ -3,7 +3,7 @@ source "https://rubygems.org" gem "appraisal", "2.2.0" -gem "bundler", "~> 1.1" +gem "bundler", "~> 2.0" gem "pry" gem "pry-byebug" gem "rake", "13.0.1" @@ -22,7 +22,7 @@ gem "spring-commands-rspec" gem "rspec-rails", "~> 4.0" gem "shoulda-context", "~> 1.2.0" gem "rails-controller-testing", ">= 1.0.1" -gem "rails", "5.2.6" +gem "rails", "5.2.8.1" gem "puma", "~> 3.11" gem "bootsnap", ">= 1.1.0", require: false gem "sass-rails", "~> 5.0" @@ -35,4 +35,4 @@ gem "chromedriver-helper" gem "listen", "~> 3.0.5" gem "spring-watcher-listen", "~> 2.0.0" gem "pg", "~> 0.18" -gem "sqlite3", "~> 1.3.6" +gem "sqlite3", "~> 1.4" diff --git a/gemfiles/rails_5_2.gemfile.lock b/gemfiles/rails_5_2.gemfile.lock index a93919146..58f7734fc 100644 --- a/gemfiles/rails_5_2.gemfile.lock +++ b/gemfiles/rails_5_2.gemfile.lock @@ -1,49 +1,49 @@ GEM remote: https://rubygems.org/ specs: - actioncable (5.2.6) - actionpack (= 5.2.6) + actioncable (5.2.8.1) + actionpack (= 5.2.8.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.6) - actionpack (= 5.2.6) - actionview (= 5.2.6) - activejob (= 5.2.6) + actionmailer (5.2.8.1) + actionpack (= 5.2.8.1) + actionview (= 5.2.8.1) + activejob (= 5.2.8.1) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.6) - actionview (= 5.2.6) - activesupport (= 5.2.6) + actionpack (5.2.8.1) + actionview (= 5.2.8.1) + activesupport (= 5.2.8.1) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.6) - activesupport (= 5.2.6) + actionview (5.2.8.1) + activesupport (= 5.2.8.1) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.6) - activesupport (= 5.2.6) + activejob (5.2.8.1) + activesupport (= 5.2.8.1) globalid (>= 0.3.6) - activemodel (5.2.6) - activesupport (= 5.2.6) - activerecord (5.2.6) - activemodel (= 5.2.6) - activesupport (= 5.2.6) + activemodel (5.2.8.1) + activesupport (= 5.2.8.1) + activerecord (5.2.8.1) + activemodel (= 5.2.8.1) + activesupport (= 5.2.8.1) arel (>= 9.0) - activestorage (5.2.6) - actionpack (= 5.2.6) - activerecord (= 5.2.6) + activestorage (5.2.8.1) + actionpack (= 5.2.8.1) + activerecord (= 5.2.8.1) marcel (~> 1.0.0) - activesupport (5.2.6) + activesupport (5.2.8.1) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) - addressable (2.7.0) - public_suffix (>= 2.0.2, < 5.0) + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) appraisal (2.2.0) bundler rake @@ -52,9 +52,9 @@ GEM io-like (~> 0.3.0) arel (9.0.0) ast (2.4.2) - bcrypt (3.1.16) - bootsnap (1.7.2) - msgpack (~> 1.0) + bcrypt (3.1.18) + bootsnap (1.13.0) + msgpack (~> 1.2) builder (3.2.4) byebug (11.1.3) capybara (3.1.1) @@ -64,44 +64,44 @@ GEM rack (>= 1.6.0) rack-test (>= 0.6.3) xpath (~> 3.0) - childprocess (3.0.0) + childprocess (4.1.0) chromedriver-helper (2.1.1) archive-zip (~> 0.10) nokogiri (~> 1.8) coderay (1.1.3) - concurrent-ruby (1.1.9) + concurrent-ruby (1.1.10) crass (1.0.6) - diff-lcs (1.4.4) - erubi (1.10.0) - ffi (1.15.0) + diff-lcs (1.5.0) + erubi (1.11.0) + ffi (1.15.5) fssm (0.2.10) - globalid (0.4.2) - activesupport (>= 4.2.0) - i18n (1.8.10) + globalid (1.0.0) + activesupport (>= 5.0) + i18n (1.12.0) concurrent-ruby (~> 1.0) io-like (0.3.1) - jbuilder (2.11.2) + jbuilder (2.11.5) + actionview (>= 5.0.0) activesupport (>= 5.0.0) + json (2.6.2) listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - loofah (2.10.0) + loofah (2.19.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) - marcel (1.0.1) + marcel (1.0.2) method_source (1.0.0) - mini_mime (1.1.0) - mini_portile2 (2.5.3) - minitest (5.14.4) - msgpack (1.4.2) - nio4r (2.5.7) - nokogiri (1.11.7) - mini_portile2 (~> 2.5.0) + mini_mime (1.1.2) + minitest (5.16.3) + msgpack (1.5.6) + nio4r (2.5.8) + nokogiri (1.13.8-x86_64-linux) racc (~> 1.4) - parallel (1.20.1) - parser (3.0.0.0) + parallel (1.22.1) + parser (3.1.2.1) ast (~> 2.4.1) pg (0.21.0) pry (0.13.1) @@ -110,24 +110,24 @@ GEM pry-byebug (3.9.0) byebug (~> 11.0) pry (~> 0.13.0) - public_suffix (4.0.6) + public_suffix (5.0.0) puma (3.12.6) - racc (1.5.2) - rack (2.2.3) - rack-test (1.1.0) - rack (>= 1.0, < 3) - rails (5.2.6) - actioncable (= 5.2.6) - actionmailer (= 5.2.6) - actionpack (= 5.2.6) - actionview (= 5.2.6) - activejob (= 5.2.6) - activemodel (= 5.2.6) - activerecord (= 5.2.6) - activestorage (= 5.2.6) - activesupport (= 5.2.6) + racc (1.6.0) + rack (2.2.4) + rack-test (2.0.2) + rack (>= 1.3) + rails (5.2.8.1) + actioncable (= 5.2.8.1) + actionmailer (= 5.2.8.1) + actionpack (= 5.2.8.1) + actionview (= 5.2.8.1) + activejob (= 5.2.8.1) + activemodel (= 5.2.8.1) + activerecord (= 5.2.8.1) + activestorage (= 5.2.8.1) + activesupport (= 5.2.8.1) bundler (>= 1.3.0) - railties (= 5.2.6) + railties (= 5.2.8.1) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -136,35 +136,35 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.3.0) + rails-html-sanitizer (1.4.3) loofah (~> 2.3) - railties (5.2.6) - actionpack (= 5.2.6) - activesupport (= 5.2.6) + railties (5.2.8.1) + actionpack (= 5.2.8.1) + activesupport (= 5.2.8.1) method_source rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) - rainbow (3.0.0) + rainbow (3.1.1) rake (13.0.1) - rb-fsevent (0.10.4) + rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) redcarpet (3.5.1) - regexp_parser (2.1.1) - rexml (3.2.4) - rouge (3.26.0) - rspec (3.10.0) - rspec-core (~> 3.10.0) - rspec-expectations (~> 3.10.0) - rspec-mocks (~> 3.10.0) - rspec-core (3.10.1) - rspec-support (~> 3.10.0) - rspec-expectations (3.10.1) + regexp_parser (2.5.0) + rexml (3.2.5) + rouge (3.30.0) + rspec (3.11.0) + rspec-core (~> 3.11.0) + rspec-expectations (~> 3.11.0) + rspec-mocks (~> 3.11.0) + rspec-core (3.11.0) + rspec-support (~> 3.11.0) + rspec-expectations (3.11.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-mocks (3.10.2) + rspec-support (~> 3.11.0) + rspec-mocks (3.11.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) + rspec-support (~> 3.11.0) rspec-rails (4.1.2) actionpack (>= 4.2) activesupport (>= 4.2) @@ -173,26 +173,27 @@ GEM rspec-expectations (~> 3.10) rspec-mocks (~> 3.10) rspec-support (~> 3.10) - rspec-support (3.10.2) - rubocop (1.10.0) + rspec-support (3.11.1) + rubocop (1.36.0) + json (~> 2.3) parallel (~> 1.10) - parser (>= 3.0.0.0) + parser (>= 3.1.2.1) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) - rexml - rubocop-ast (>= 1.2.0, < 2.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.20.1, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.4.1) - parser (>= 2.7.1.5) - rubocop-packaging (0.5.1) - rubocop (>= 0.89, < 2.0) - rubocop-rails (2.9.1) + rubocop-ast (1.21.0) + parser (>= 3.1.1.0) + rubocop-packaging (0.5.2) + rubocop (>= 1.33, < 2.0) + rubocop-rails (2.16.1) activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 0.90.0, < 2.0) + rubocop (>= 1.33.0, < 2.0) ruby-progressbar (1.11.0) - rubyzip (2.3.0) + rubyzip (2.3.2) sass (3.7.4) sass-listen (~> 4.0.0) sass-listen (4.0.0) @@ -204,8 +205,9 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) + selenium-webdriver (4.1.0) + childprocess (>= 0.5, < 5.0) + rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2) shoulda-context (1.2.2) spring (2.1.1) @@ -217,38 +219,40 @@ GEM sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.2.2) - actionpack (>= 4.0) - activesupport (>= 4.0) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) sprockets (>= 3.0.0) - sqlite3 (1.3.13) - thor (1.1.0) + sqlite3 (1.5.0-x86_64-linux) + thor (1.2.1) thread_safe (0.3.6) - tilt (2.0.10) + tilt (2.0.11) turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) - tzinfo (1.2.9) + tzinfo (1.2.10) thread_safe (~> 0.1) - unicode-display_width (2.0.0) + unicode-display_width (2.3.0) warnings_logger (0.1.1) + webrick (1.7.0) websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - yard (0.9.26) + yard (0.9.28) + webrick (~> 1.7.0) zeus (0.15.14) method_source (>= 0.6.7) PLATFORMS - ruby + x86_64-linux DEPENDENCIES appraisal (= 2.2.0) bcrypt (~> 3.1.7) bootsnap (>= 1.1.0) - bundler (~> 1.1) + bundler (~> 2.0) capybara (~> 3.1.1) chromedriver-helper fssm @@ -258,7 +262,7 @@ DEPENDENCIES pry pry-byebug puma (~> 3.11) - rails (= 5.2.6) + rails (= 5.2.8.1) rails-controller-testing (>= 1.0.1) rake (= 13.0.1) redcarpet @@ -274,11 +278,11 @@ DEPENDENCIES spring spring-commands-rspec spring-watcher-listen (~> 2.0.0) - sqlite3 (~> 1.3.6) + sqlite3 (~> 1.4) turbolinks (~> 5) warnings_logger yard zeus BUNDLED WITH - 1.17.3 + 2.3.22 diff --git a/gemfiles/rails_6_0.gemfile b/gemfiles/rails_6_0.gemfile index 002754b83..81c323c47 100644 --- a/gemfiles/rails_6_0.gemfile +++ b/gemfiles/rails_6_0.gemfile @@ -3,7 +3,7 @@ source "https://rubygems.org" gem "appraisal", "2.2.0" -gem "bundler", "~> 1.1" +gem "bundler", "~> 2.0" gem "pry" gem "pry-byebug" gem "rake", "13.0.1" @@ -22,7 +22,7 @@ gem "spring-commands-rspec" gem "rspec-rails", "~> 4.0" gem "shoulda-context", "~> 1.2.0" gem "rails-controller-testing", ">= 1.0.1" -gem "rails", "6.0.4" +gem "rails", "6.0.6" gem "puma", "~> 4.1" gem "bootsnap", ">= 1.4.2", require: false gem "sass-rails", ">= 6" @@ -31,9 +31,10 @@ gem "jbuilder", "~> 2.7" gem "bcrypt", "~> 3.1.7" gem "capybara", ">= 2.15" gem "listen", "~> 3.3.0" +gem "psych", "~> 3.0" gem "spring-watcher-listen", "~> 2.0.0" gem "selenium-webdriver" gem "webdrivers" -gem "actiontext", "~> 6.0.4" +gem "net-smtp", require: false gem "pg", ">= 0.18", "< 2.0" gem "sqlite3", "~> 1.4" diff --git a/gemfiles/rails_6_0.gemfile.lock b/gemfiles/rails_6_0.gemfile.lock index fcfaef705..b1dedfdcc 100644 --- a/gemfiles/rails_6_0.gemfile.lock +++ b/gemfiles/rails_6_0.gemfile.lock @@ -1,144 +1,154 @@ GEM remote: https://rubygems.org/ specs: - actioncable (6.0.4) - actionpack (= 6.0.4) + actioncable (6.0.6) + actionpack (= 6.0.6) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.4) - actionpack (= 6.0.4) - activejob (= 6.0.4) - activerecord (= 6.0.4) - activestorage (= 6.0.4) - activesupport (= 6.0.4) + actionmailbox (6.0.6) + actionpack (= 6.0.6) + activejob (= 6.0.6) + activerecord (= 6.0.6) + activestorage (= 6.0.6) + activesupport (= 6.0.6) mail (>= 2.7.1) - actionmailer (6.0.4) - actionpack (= 6.0.4) - actionview (= 6.0.4) - activejob (= 6.0.4) + actionmailer (6.0.6) + actionpack (= 6.0.6) + actionview (= 6.0.6) + activejob (= 6.0.6) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.4) - actionview (= 6.0.4) - activesupport (= 6.0.4) + actionpack (6.0.6) + actionview (= 6.0.6) + activesupport (= 6.0.6) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.4) - actionpack (= 6.0.4) - activerecord (= 6.0.4) - activestorage (= 6.0.4) - activesupport (= 6.0.4) + actiontext (6.0.6) + actionpack (= 6.0.6) + activerecord (= 6.0.6) + activestorage (= 6.0.6) + activesupport (= 6.0.6) nokogiri (>= 1.8.5) - actionview (6.0.4) - activesupport (= 6.0.4) + actionview (6.0.6) + activesupport (= 6.0.6) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.4) - activesupport (= 6.0.4) + activejob (6.0.6) + activesupport (= 6.0.6) globalid (>= 0.3.6) - activemodel (6.0.4) - activesupport (= 6.0.4) - activerecord (6.0.4) - activemodel (= 6.0.4) - activesupport (= 6.0.4) - activestorage (6.0.4) - actionpack (= 6.0.4) - activejob (= 6.0.4) - activerecord (= 6.0.4) - marcel (~> 1.0.0) - activesupport (6.0.4) + activemodel (6.0.6) + activesupport (= 6.0.6) + activerecord (6.0.6) + activemodel (= 6.0.6) + activesupport (= 6.0.6) + activestorage (6.0.6) + actionpack (= 6.0.6) + activejob (= 6.0.6) + activerecord (= 6.0.6) + marcel (~> 1.0) + activesupport (6.0.6) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - addressable (2.7.0) - public_suffix (>= 2.0.2, < 5.0) + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) appraisal (2.2.0) bundler rake thor (>= 0.14.0) ast (2.4.2) - bcrypt (3.1.16) - bootsnap (1.7.2) - msgpack (~> 1.0) + bcrypt (3.1.18) + bootsnap (1.13.0) + msgpack (~> 1.2) builder (3.2.4) byebug (11.1.3) - capybara (3.35.3) + capybara (3.36.0) addressable + matrix mini_mime (>= 0.1.3) nokogiri (~> 1.8) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - childprocess (3.0.0) + childprocess (4.1.0) coderay (1.1.3) - concurrent-ruby (1.1.9) + concurrent-ruby (1.1.10) crass (1.0.6) - diff-lcs (1.4.4) - erubi (1.10.0) - ffi (1.15.0) + diff-lcs (1.5.0) + digest (3.1.0) + erubi (1.11.0) + ffi (1.15.5) fssm (0.2.10) - globalid (0.4.2) - activesupport (>= 4.2.0) - i18n (1.8.10) + globalid (1.0.0) + activesupport (>= 5.0) + i18n (1.12.0) concurrent-ruby (~> 1.0) - jbuilder (2.11.2) + jbuilder (2.11.5) + actionview (>= 5.0.0) activesupport (>= 5.0.0) + json (2.6.2) listen (3.3.4) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - loofah (2.10.0) + loofah (2.19.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) - marcel (1.0.1) + marcel (1.0.2) + matrix (0.4.2) method_source (1.0.0) - mini_mime (1.1.0) - mini_portile2 (2.5.3) - minitest (5.14.4) - msgpack (1.4.2) - nio4r (2.5.7) - nokogiri (1.11.7) - mini_portile2 (~> 2.5.0) + mini_mime (1.1.2) + minitest (5.16.3) + msgpack (1.5.6) + net-protocol (0.1.3) + timeout + net-smtp (0.3.1) + digest + net-protocol + timeout + nio4r (2.5.8) + nokogiri (1.13.8-x86_64-linux) racc (~> 1.4) - parallel (1.20.1) - parser (3.0.0.0) + parallel (1.22.1) + parser (3.1.2.1) ast (~> 2.4.1) - pg (1.2.3) + pg (1.4.3) pry (0.13.1) coderay (~> 1.1) method_source (~> 1.0) pry-byebug (3.9.0) byebug (~> 11.0) pry (~> 0.13.0) - public_suffix (4.0.6) - puma (4.3.7) + psych (3.3.3) + public_suffix (5.0.0) + puma (4.3.12) nio4r (~> 2.0) - racc (1.5.2) - rack (2.2.3) - rack-test (1.1.0) - rack (>= 1.0, < 3) - rails (6.0.4) - actioncable (= 6.0.4) - actionmailbox (= 6.0.4) - actionmailer (= 6.0.4) - actionpack (= 6.0.4) - actiontext (= 6.0.4) - actionview (= 6.0.4) - activejob (= 6.0.4) - activemodel (= 6.0.4) - activerecord (= 6.0.4) - activestorage (= 6.0.4) - activesupport (= 6.0.4) + racc (1.6.0) + rack (2.2.4) + rack-test (2.0.2) + rack (>= 1.3) + rails (6.0.6) + actioncable (= 6.0.6) + actionmailbox (= 6.0.6) + actionmailer (= 6.0.6) + actionpack (= 6.0.6) + actiontext (= 6.0.6) + actionview (= 6.0.6) + activejob (= 6.0.6) + activemodel (= 6.0.6) + activerecord (= 6.0.6) + activestorage (= 6.0.6) + activesupport (= 6.0.6) bundler (>= 1.3.0) - railties (= 6.0.4) + railties (= 6.0.6) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -147,35 +157,35 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.3.0) + rails-html-sanitizer (1.4.3) loofah (~> 2.3) - railties (6.0.4) - actionpack (= 6.0.4) - activesupport (= 6.0.4) + railties (6.0.6) + actionpack (= 6.0.6) + activesupport (= 6.0.6) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) - rainbow (3.0.0) + rainbow (3.1.1) rake (13.0.1) - rb-fsevent (0.10.4) + rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) redcarpet (3.5.1) - regexp_parser (2.1.1) - rexml (3.2.4) - rouge (3.26.0) - rspec (3.10.0) - rspec-core (~> 3.10.0) - rspec-expectations (~> 3.10.0) - rspec-mocks (~> 3.10.0) - rspec-core (3.10.1) - rspec-support (~> 3.10.0) - rspec-expectations (3.10.1) + regexp_parser (2.6.0) + rexml (3.2.5) + rouge (3.30.0) + rspec (3.11.0) + rspec-core (~> 3.11.0) + rspec-expectations (~> 3.11.0) + rspec-mocks (~> 3.11.0) + rspec-core (3.11.0) + rspec-support (~> 3.11.0) + rspec-expectations (3.11.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-mocks (3.10.2) + rspec-support (~> 3.11.0) + rspec-mocks (3.11.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) + rspec-support (~> 3.11.0) rspec-rails (4.1.2) actionpack (>= 4.2) activesupport (>= 4.2) @@ -184,26 +194,27 @@ GEM rspec-expectations (~> 3.10) rspec-mocks (~> 3.10) rspec-support (~> 3.10) - rspec-support (3.10.2) - rubocop (1.10.0) + rspec-support (3.11.1) + rubocop (1.36.0) + json (~> 2.3) parallel (~> 1.10) - parser (>= 3.0.0.0) + parser (>= 3.1.2.1) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) - rexml - rubocop-ast (>= 1.2.0, < 2.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.20.1, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.4.1) - parser (>= 2.7.1.5) - rubocop-packaging (0.5.1) - rubocop (>= 0.89, < 2.0) - rubocop-rails (2.9.1) + rubocop-ast (1.21.0) + parser (>= 3.1.1.0) + rubocop-packaging (0.5.2) + rubocop (>= 1.33, < 2.0) + rubocop-rails (2.16.1) activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 0.90.0, < 2.0) + rubocop (>= 1.33.0, < 2.0) ruby-progressbar (1.11.0) - rubyzip (2.3.0) + rubyzip (2.3.2) sass-rails (6.0.0) sassc-rails (~> 2.1, >= 2.1.1) sassc (2.4.0) @@ -214,8 +225,9 @@ GEM sprockets (> 3.0) sprockets-rails tilt - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) + selenium-webdriver (4.1.0) + childprocess (>= 0.5, < 5.0) + rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2) shoulda-context (1.2.2) spring (2.1.1) @@ -224,56 +236,60 @@ GEM spring-watcher-listen (2.0.1) listen (>= 2.7, < 4.0) spring (>= 1.2, < 3.0) - sprockets (4.0.2) + sprockets (4.1.1) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.2.2) - actionpack (>= 4.0) - activesupport (>= 4.0) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) sprockets (>= 3.0.0) - sqlite3 (1.4.2) - thor (1.1.0) + sqlite3 (1.5.0-x86_64-linux) + thor (1.2.1) thread_safe (0.3.6) - tilt (2.0.10) + tilt (2.0.11) + timeout (0.3.0) turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) - tzinfo (1.2.9) + tzinfo (1.2.10) thread_safe (~> 0.1) - unicode-display_width (2.0.0) + unicode-display_width (2.3.0) warnings_logger (0.1.1) - webdrivers (4.6.0) + webdrivers (5.1.0) nokogiri (~> 1.6) rubyzip (>= 1.3.0) - selenium-webdriver (>= 3.0, < 4.0) + selenium-webdriver (~> 4.0) + webrick (1.7.0) websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - yard (0.9.26) - zeitwerk (2.4.2) + yard (0.9.28) + webrick (~> 1.7.0) + zeitwerk (2.6.0) zeus (0.15.14) method_source (>= 0.6.7) PLATFORMS - ruby + x86_64-linux DEPENDENCIES - actiontext (~> 6.0.4) appraisal (= 2.2.0) bcrypt (~> 3.1.7) bootsnap (>= 1.4.2) - bundler (~> 1.1) + bundler (~> 2.0) capybara (>= 2.15) fssm jbuilder (~> 2.7) listen (~> 3.3.0) + net-smtp pg (>= 0.18, < 2.0) pry pry-byebug + psych (~> 3.0) puma (~> 4.1) - rails (= 6.0.4) + rails (= 6.0.6) rails-controller-testing (>= 1.0.1) rake (= 13.0.1) redcarpet @@ -297,4 +313,4 @@ DEPENDENCIES zeus BUNDLED WITH - 1.17.3 + 2.3.22 diff --git a/gemfiles/rails_6_1.gemfile b/gemfiles/rails_6_1.gemfile index beba5e762..6547c1417 100644 --- a/gemfiles/rails_6_1.gemfile +++ b/gemfiles/rails_6_1.gemfile @@ -3,7 +3,7 @@ source "https://rubygems.org" gem "appraisal", "2.2.0" -gem "bundler", "~> 1.1" +gem "bundler", "~> 2.0" gem "pry" gem "pry-byebug" gem "rake", "13.0.1" @@ -22,7 +22,7 @@ gem "spring-commands-rspec" gem "rspec-rails", "~> 4.0" gem "shoulda-context", "~> 1.2.0" gem "rails-controller-testing", ">= 1.0.1" -gem "rails", "6.1.4" +gem "rails", "6.1.7" gem "puma", "~> 5.0" gem "bootsnap", ">= 1.4.2", require: false gem "sass-rails", ">= 6" @@ -31,10 +31,11 @@ gem "jbuilder", "~> 2.7" gem "bcrypt", "~> 3.1.7" gem "capybara", ">= 2.15" gem "listen", ">= 3.0.5", "< 3.6" +gem "net-smtp", require: false +gem "psych", "~> 3.0" gem "rack-mini-profiler", "~> 2.0.0" gem "spring-watcher-listen", "~> 2.0.0" gem "selenium-webdriver" gem "webdrivers" -gem "actiontext", "~> 6.1.4" gem "pg", ">= 0.18", "< 2.0" gem "sqlite3", "~> 1.4" diff --git a/gemfiles/rails_6_1.gemfile.lock b/gemfiles/rails_6_1.gemfile.lock index 9104f2f9f..b9f63878f 100644 --- a/gemfiles/rails_6_1.gemfile.lock +++ b/gemfiles/rails_6_1.gemfile.lock @@ -1,66 +1,66 @@ GEM remote: https://rubygems.org/ specs: - actioncable (6.1.4) - actionpack (= 6.1.4) - activesupport (= 6.1.4) + actioncable (6.1.7) + actionpack (= 6.1.7) + activesupport (= 6.1.7) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.1.4) - actionpack (= 6.1.4) - activejob (= 6.1.4) - activerecord (= 6.1.4) - activestorage (= 6.1.4) - activesupport (= 6.1.4) + actionmailbox (6.1.7) + actionpack (= 6.1.7) + activejob (= 6.1.7) + activerecord (= 6.1.7) + activestorage (= 6.1.7) + activesupport (= 6.1.7) mail (>= 2.7.1) - actionmailer (6.1.4) - actionpack (= 6.1.4) - actionview (= 6.1.4) - activejob (= 6.1.4) - activesupport (= 6.1.4) + actionmailer (6.1.7) + actionpack (= 6.1.7) + actionview (= 6.1.7) + activejob (= 6.1.7) + activesupport (= 6.1.7) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.1.4) - actionview (= 6.1.4) - activesupport (= 6.1.4) + actionpack (6.1.7) + actionview (= 6.1.7) + activesupport (= 6.1.7) rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.1.4) - actionpack (= 6.1.4) - activerecord (= 6.1.4) - activestorage (= 6.1.4) - activesupport (= 6.1.4) + actiontext (6.1.7) + actionpack (= 6.1.7) + activerecord (= 6.1.7) + activestorage (= 6.1.7) + activesupport (= 6.1.7) nokogiri (>= 1.8.5) - actionview (6.1.4) - activesupport (= 6.1.4) + actionview (6.1.7) + activesupport (= 6.1.7) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.1.4) - activesupport (= 6.1.4) + activejob (6.1.7) + activesupport (= 6.1.7) globalid (>= 0.3.6) - activemodel (6.1.4) - activesupport (= 6.1.4) - activerecord (6.1.4) - activemodel (= 6.1.4) - activesupport (= 6.1.4) - activestorage (6.1.4) - actionpack (= 6.1.4) - activejob (= 6.1.4) - activerecord (= 6.1.4) - activesupport (= 6.1.4) - marcel (~> 1.0.0) + activemodel (6.1.7) + activesupport (= 6.1.7) + activerecord (6.1.7) + activemodel (= 6.1.7) + activesupport (= 6.1.7) + activestorage (6.1.7) + actionpack (= 6.1.7) + activejob (= 6.1.7) + activerecord (= 6.1.7) + activesupport (= 6.1.7) + marcel (~> 1.0) mini_mime (>= 1.1.0) - activesupport (6.1.4) + activesupport (6.1.7) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) zeitwerk (~> 2.3) - addressable (2.7.0) + addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) appraisal (2.2.0) bundler @@ -68,83 +68,94 @@ GEM thor (>= 0.14.0) ast (2.4.2) bcrypt (3.1.16) - bootsnap (1.7.2) - msgpack (~> 1.0) + bootsnap (1.10.2) + msgpack (~> 1.2) builder (3.2.4) byebug (11.1.3) - capybara (3.35.3) + capybara (3.36.0) addressable + matrix mini_mime (>= 0.1.3) nokogiri (~> 1.8) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - childprocess (3.0.0) + childprocess (4.1.0) coderay (1.1.3) - concurrent-ruby (1.1.9) + concurrent-ruby (1.1.10) crass (1.0.6) - diff-lcs (1.4.4) - erubi (1.10.0) - ffi (1.15.0) + diff-lcs (1.5.0) + digest (3.1.0) + erubi (1.11.0) + ffi (1.15.5) fssm (0.2.10) - globalid (0.4.2) - activesupport (>= 4.2.0) - i18n (1.8.10) + globalid (1.0.0) + activesupport (>= 5.0) + i18n (1.12.0) concurrent-ruby (~> 1.0) - jbuilder (2.11.2) + jbuilder (2.11.5) + actionview (>= 5.0.0) activesupport (>= 5.0.0) listen (3.5.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - loofah (2.10.0) + loofah (2.19.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) - marcel (1.0.1) + marcel (1.0.2) + matrix (0.4.2) method_source (1.0.0) - mini_mime (1.1.0) - mini_portile2 (2.5.3) - minitest (5.14.4) - msgpack (1.4.2) - nio4r (2.5.7) - nokogiri (1.11.7) - mini_portile2 (~> 2.5.0) + mini_mime (1.1.2) + mini_portile2 (2.8.0) + minitest (5.16.3) + msgpack (1.4.4) + net-protocol (0.1.3) + timeout + net-smtp (0.3.1) + digest + net-protocol + timeout + nio4r (2.5.8) + nokogiri (1.13.8) + mini_portile2 (~> 2.8.0) racc (~> 1.4) - parallel (1.20.1) - parser (3.0.0.0) + parallel (1.21.0) + parser (3.1.0.0) ast (~> 2.4.1) - pg (1.2.3) - pry (0.14.0) + pg (1.3.0) + pry (0.14.1) coderay (~> 1.1) method_source (~> 1.0) pry-byebug (3.8.0) byebug (~> 11.0) pry (~> 0.10) + psych (3.3.2) public_suffix (4.0.6) - puma (5.2.2) + puma (5.6.1) nio4r (~> 2.0) - racc (1.5.2) - rack (2.2.3) + racc (1.6.0) + rack (2.2.4) rack-mini-profiler (2.0.4) rack (>= 1.2.0) - rack-test (1.1.0) - rack (>= 1.0, < 3) - rails (6.1.4) - actioncable (= 6.1.4) - actionmailbox (= 6.1.4) - actionmailer (= 6.1.4) - actionpack (= 6.1.4) - actiontext (= 6.1.4) - actionview (= 6.1.4) - activejob (= 6.1.4) - activemodel (= 6.1.4) - activerecord (= 6.1.4) - activestorage (= 6.1.4) - activesupport (= 6.1.4) + rack-test (2.0.2) + rack (>= 1.3) + rails (6.1.7) + actioncable (= 6.1.7) + actionmailbox (= 6.1.7) + actionmailer (= 6.1.7) + actionpack (= 6.1.7) + actiontext (= 6.1.7) + actionview (= 6.1.7) + activejob (= 6.1.7) + activemodel (= 6.1.7) + activerecord (= 6.1.7) + activestorage (= 6.1.7) + activesupport (= 6.1.7) bundler (>= 1.15.0) - railties (= 6.1.4) + railties (= 6.1.7) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -153,63 +164,63 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.3.0) + rails-html-sanitizer (1.4.3) loofah (~> 2.3) - railties (6.1.4) - actionpack (= 6.1.4) - activesupport (= 6.1.4) + railties (6.1.7) + actionpack (= 6.1.7) + activesupport (= 6.1.7) method_source - rake (>= 0.13) + rake (>= 12.2) thor (~> 1.0) - rainbow (3.0.0) + rainbow (3.1.1) rake (13.0.1) - rb-fsevent (0.10.4) + rb-fsevent (0.11.0) rb-inotify (0.10.1) ffi (~> 1.0) redcarpet (3.5.1) - regexp_parser (2.0.3) - rexml (3.2.4) - rouge (3.26.0) - rspec (3.9.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) - rspec-core (3.9.3) - rspec-support (~> 3.9.3) - rspec-expectations (3.9.4) + regexp_parser (2.2.0) + rexml (3.2.5) + rouge (3.27.0) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.2) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-mocks (3.9.1) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.3) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-rails (4.0.1) + rspec-support (~> 3.10.0) + rspec-rails (4.1.2) actionpack (>= 4.2) activesupport (>= 4.2) railties (>= 4.2) - rspec-core (~> 3.9) - rspec-expectations (~> 3.9) - rspec-mocks (~> 3.9) - rspec-support (~> 3.9) - rspec-support (3.9.4) - rubocop (1.10.0) + rspec-core (~> 3.10) + rspec-expectations (~> 3.10) + rspec-mocks (~> 3.10) + rspec-support (~> 3.10) + rspec-support (3.10.3) + rubocop (1.25.0) parallel (~> 1.10) - parser (>= 3.0.0.0) + parser (>= 3.1.0.0) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml - rubocop-ast (>= 1.2.0, < 2.0) + rubocop-ast (>= 1.15.1, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.4.1) - parser (>= 2.7.1.5) + rubocop-ast (1.15.1) + parser (>= 3.0.1.1) rubocop-packaging (0.5.1) rubocop (>= 0.89, < 2.0) - rubocop-rails (2.9.1) + rubocop-rails (2.13.2) activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 0.90.0, < 2.0) + rubocop (>= 1.7.0, < 2.0) ruby-progressbar (1.11.0) - rubyzip (2.3.0) + rubyzip (2.3.2) sass-rails (6.0.0) sassc-rails (~> 2.1, >= 2.1.1) sassc (2.4.0) @@ -220,8 +231,9 @@ GEM sprockets (> 3.0) sprockets-rails tilt - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) + selenium-webdriver (4.1.0) + childprocess (>= 0.5, < 5.0) + rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2) shoulda-context (1.2.2) spring (2.1.1) @@ -230,34 +242,37 @@ GEM spring-watcher-listen (2.0.1) listen (>= 2.7, < 4.0) spring (>= 1.2, < 3.0) - sprockets (4.0.2) + sprockets (4.1.1) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.2.2) - actionpack (>= 4.0) - activesupport (>= 4.0) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) sprockets (>= 3.0.0) sqlite3 (1.4.2) - thor (1.1.0) + thor (1.2.1) tilt (2.0.10) + timeout (0.3.0) turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) - tzinfo (2.0.4) + tzinfo (2.0.5) concurrent-ruby (~> 1.0) - unicode-display_width (2.0.0) + unicode-display_width (2.1.0) warnings_logger (0.1.1) - webdrivers (4.5.0) + webdrivers (5.0.0) nokogiri (~> 1.6) rubyzip (>= 1.3.0) - selenium-webdriver (>= 3.0, < 4.0) + selenium-webdriver (~> 4.0) + webrick (1.7.0) websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - yard (0.9.26) - zeitwerk (2.4.2) + yard (0.9.27) + webrick (~> 1.7.0) + zeitwerk (2.6.0) zeus (0.15.14) method_source (>= 0.6.7) @@ -265,21 +280,22 @@ PLATFORMS ruby DEPENDENCIES - actiontext (~> 6.1.4) appraisal (= 2.2.0) bcrypt (~> 3.1.7) bootsnap (>= 1.4.2) - bundler (~> 1.1) + bundler (~> 2.0) capybara (>= 2.15) fssm jbuilder (~> 2.7) listen (>= 3.0.5, < 3.6) + net-smtp pg (>= 0.18, < 2.0) pry pry-byebug + psych (~> 3.0) puma (~> 5.0) rack-mini-profiler (~> 2.0.0) - rails (= 6.1.4) + rails (= 6.1.7) rails-controller-testing (>= 1.0.1) rake (= 13.0.1) redcarpet @@ -303,4 +319,4 @@ DEPENDENCIES zeus BUNDLED WITH - 1.17.3 + 2.3.22 diff --git a/gemfiles/rails_7_0.gemfile b/gemfiles/rails_7_0.gemfile new file mode 100644 index 000000000..cd23b1569 --- /dev/null +++ b/gemfiles/rails_7_0.gemfile @@ -0,0 +1,40 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "appraisal", "2.2.0" +gem "bundler", "~> 2.0" +gem "pry" +gem "pry-byebug" +gem "rake", "13.0.1" +gem "rspec", "~> 3.9" +gem "rubocop", require: false +gem "rubocop-packaging", require: false +gem "rubocop-rails", require: false +gem "warnings_logger" +gem "zeus", require: false +gem "fssm" +gem "redcarpet" +gem "rouge" +gem "yard" +gem "spring" +gem "spring-commands-rspec" +gem "rspec-rails", "~> 4.0" +gem "shoulda-context", "~> 1.2.0" +gem "rails", "~> 7.0.1" +gem "sprockets-rails" +gem "puma", "~> 5.0" +gem "importmap-rails" +gem "turbo-rails" +gem "stimulus-rails" +gem "jbuilder" +gem "redis", "~> 4.0" +gem "bootsnap", require: false +gem "capybara" +gem "selenium-webdriver" +gem "webdrivers" +gem "bcrypt", "~> 3.1.7" +gem "rails-controller-testing" +gem "debug", platforms: [:mri, :mingw, :x64_mingw] +gem "sqlite3", "~> 1.4" +gem "pg", "~> 1.1" diff --git a/gemfiles/rails_7_0.gemfile.lock b/gemfiles/rails_7_0.gemfile.lock new file mode 100644 index 000000000..6747aa24e --- /dev/null +++ b/gemfiles/rails_7_0.gemfile.lock @@ -0,0 +1,318 @@ +GEM + remote: https://rubygems.org/ + specs: + actioncable (7.0.4) + actionpack (= 7.0.4) + activesupport (= 7.0.4) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailbox (7.0.4) + actionpack (= 7.0.4) + activejob (= 7.0.4) + activerecord (= 7.0.4) + activestorage (= 7.0.4) + activesupport (= 7.0.4) + mail (>= 2.7.1) + net-imap + net-pop + net-smtp + actionmailer (7.0.4) + actionpack (= 7.0.4) + actionview (= 7.0.4) + activejob (= 7.0.4) + activesupport (= 7.0.4) + mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp + rails-dom-testing (~> 2.0) + actionpack (7.0.4) + actionview (= 7.0.4) + activesupport (= 7.0.4) + rack (~> 2.0, >= 2.2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (7.0.4) + actionpack (= 7.0.4) + activerecord (= 7.0.4) + activestorage (= 7.0.4) + activesupport (= 7.0.4) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (7.0.4) + activesupport (= 7.0.4) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (7.0.4) + activesupport (= 7.0.4) + globalid (>= 0.3.6) + activemodel (7.0.4) + activesupport (= 7.0.4) + activerecord (7.0.4) + activemodel (= 7.0.4) + activesupport (= 7.0.4) + activestorage (7.0.4) + actionpack (= 7.0.4) + activejob (= 7.0.4) + activerecord (= 7.0.4) + activesupport (= 7.0.4) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (7.0.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + addressable (2.8.0) + public_suffix (>= 2.0.2, < 5.0) + appraisal (2.2.0) + bundler + rake + thor (>= 0.14.0) + ast (2.4.2) + bcrypt (3.1.16) + bootsnap (1.10.2) + msgpack (~> 1.2) + builder (3.2.4) + byebug (11.1.3) + capybara (3.36.0) + addressable + matrix + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + childprocess (4.1.0) + coderay (1.1.3) + concurrent-ruby (1.1.10) + crass (1.0.6) + debug (1.4.0) + irb (>= 1.3.6) + reline (>= 0.2.7) + diff-lcs (1.5.0) + erubi (1.11.0) + fssm (0.2.10) + globalid (1.0.0) + activesupport (>= 5.0) + i18n (1.12.0) + concurrent-ruby (~> 1.0) + importmap-rails (1.0.2) + actionpack (>= 6.0.0) + railties (>= 6.0.0) + io-console (0.5.11) + irb (1.4.1) + reline (>= 0.3.0) + jbuilder (2.11.5) + actionview (>= 5.0.0) + activesupport (>= 5.0.0) + loofah (2.19.0) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.1) + mini_mime (>= 0.1.1) + marcel (1.0.2) + matrix (0.4.2) + method_source (1.0.0) + mini_mime (1.1.2) + mini_portile2 (2.8.0) + minitest (5.16.3) + msgpack (1.4.4) + net-imap (0.3.1) + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.1.3) + timeout + net-smtp (0.3.2) + net-protocol + nio4r (2.5.8) + nokogiri (1.13.8) + mini_portile2 (~> 2.8.0) + racc (~> 1.4) + parallel (1.21.0) + parser (3.1.0.0) + ast (~> 2.4.1) + pg (1.3.0) + pry (0.13.1) + coderay (~> 1.1) + method_source (~> 1.0) + pry-byebug (3.9.0) + byebug (~> 11.0) + pry (~> 0.13.0) + public_suffix (4.0.6) + puma (5.5.2) + nio4r (~> 2.0) + racc (1.6.0) + rack (2.2.4) + rack-test (2.0.2) + rack (>= 1.3) + rails (7.0.4) + actioncable (= 7.0.4) + actionmailbox (= 7.0.4) + actionmailer (= 7.0.4) + actionpack (= 7.0.4) + actiontext (= 7.0.4) + actionview (= 7.0.4) + activejob (= 7.0.4) + activemodel (= 7.0.4) + activerecord (= 7.0.4) + activestorage (= 7.0.4) + activesupport (= 7.0.4) + bundler (>= 1.15.0) + railties (= 7.0.4) + rails-controller-testing (1.0.5) + actionpack (>= 5.0.1.rc1) + actionview (>= 5.0.1.rc1) + activesupport (>= 5.0.1.rc1) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.4.3) + loofah (~> 2.3) + railties (7.0.4) + actionpack (= 7.0.4) + activesupport (= 7.0.4) + method_source + rake (>= 12.2) + thor (~> 1.0) + zeitwerk (~> 2.5) + rainbow (3.1.1) + rake (13.0.1) + redcarpet (3.5.1) + redis (4.5.1) + regexp_parser (2.2.0) + reline (0.3.1) + io-console (~> 0.5) + rexml (3.2.5) + rouge (3.26.0) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-rails (4.1.2) + actionpack (>= 4.2) + activesupport (>= 4.2) + railties (>= 4.2) + rspec-core (~> 3.10) + rspec-expectations (~> 3.10) + rspec-mocks (~> 3.10) + rspec-support (~> 3.10) + rspec-support (3.10.3) + rubocop (1.25.0) + parallel (~> 1.10) + parser (>= 3.1.0.0) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml + rubocop-ast (>= 1.15.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.15.1) + parser (>= 3.0.1.1) + rubocop-packaging (0.5.1) + rubocop (>= 0.89, < 2.0) + rubocop-rails (2.13.1) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 1.7.0, < 2.0) + ruby-progressbar (1.11.0) + rubyzip (2.3.2) + selenium-webdriver (4.1.0) + childprocess (>= 0.5, < 5.0) + rexml (~> 3.2, >= 3.2.5) + rubyzip (>= 1.2.2) + shoulda-context (1.2.2) + spring (4.0.0) + spring-commands-rspec (1.0.4) + spring (>= 0.9.1) + sprockets (4.0.2) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) + sprockets (>= 3.0.0) + sqlite3 (1.4.2) + stimulus-rails (1.0.2) + railties (>= 6.0.0) + thor (1.2.1) + timeout (0.3.0) + turbo-rails (1.0.1) + actionpack (>= 6.0.0) + railties (>= 6.0.0) + tzinfo (2.0.5) + concurrent-ruby (~> 1.0) + unicode-display_width (2.1.0) + warnings_logger (0.1.1) + webdrivers (5.0.0) + nokogiri (~> 1.6) + rubyzip (>= 1.3.0) + selenium-webdriver (~> 4.0) + webrick (1.7.0) + websocket-driver (0.7.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) + yard (0.9.27) + webrick (~> 1.7.0) + zeitwerk (2.6.0) + zeus (0.15.14) + method_source (>= 0.6.7) + +PLATFORMS + ruby + +DEPENDENCIES + appraisal (= 2.2.0) + bcrypt (~> 3.1.7) + bootsnap + bundler (~> 2.0) + capybara + debug + fssm + importmap-rails + jbuilder + pg (~> 1.1) + pry + pry-byebug + puma (~> 5.0) + rails (~> 7.0.1) + rails-controller-testing + rake (= 13.0.1) + redcarpet + redis (~> 4.0) + rouge + rspec (~> 3.9) + rspec-rails (~> 4.0) + rubocop + rubocop-packaging + rubocop-rails + selenium-webdriver + shoulda-context (~> 1.2.0) + spring + spring-commands-rspec + sprockets-rails + sqlite3 (~> 1.4) + stimulus-rails + turbo-rails + warnings_logger + webdrivers + yard + zeus + +BUNDLED WITH + 2.3.6 diff --git a/lib/shoulda/matchers/active_model.rb b/lib/shoulda/matchers/active_model.rb index e4a0ad7bb..c9f20d49b 100644 --- a/lib/shoulda/matchers/active_model.rb +++ b/lib/shoulda/matchers/active_model.rb @@ -26,6 +26,8 @@ require 'shoulda/matchers/active_model/numericality_matchers/odd_number_matcher' require 'shoulda/matchers/active_model/numericality_matchers/even_number_matcher' require 'shoulda/matchers/active_model/numericality_matchers/only_integer_matcher' +require 'shoulda/matchers/active_model/numericality_matchers/range_matcher' +require 'shoulda/matchers/active_model/numericality_matchers/submatchers' require 'shoulda/matchers/active_model/errors' require 'shoulda/matchers/active_model/have_secure_password_matcher' diff --git a/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb b/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb index 8d41b92db..2bea2de52 100644 --- a/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +++ b/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/module/delegation' + module Shoulda module Matchers module ActiveModel @@ -31,6 +33,8 @@ class ComparisonMatcher < ValidationMatcher }, }.freeze + delegate :failure_message, :failure_message_when_negated, to: :submatchers + def initialize(numericality_matcher, value, operator) super(nil) unless numericality_matcher.respond_to? :diff_to_compare @@ -72,49 +76,24 @@ def expects_custom_validation_message? def matches?(subject) @subject = subject - all_bounds_correct? - end - - def failure_message - last_failing_submatcher.failure_message - end - - def failure_message_when_negated - last_failing_submatcher.failure_message_when_negated + submatchers.matches?(subject) end def comparison_description "#{comparison_expectation} #{@value}" end - private - - def all_bounds_correct? - failing_submatchers.empty? - end - - def failing_submatchers - submatchers_and_results. - select { |x| !x[:matched] }. - map { |x| x[:matcher] } - end - - def last_failing_submatcher - failing_submatchers.last - end - def submatchers - @_submatchers ||= - comparison_combos.map do |diff, submatcher_method_name| - matcher = __send__(submatcher_method_name, diff, nil) - matcher.with_message(@message, values: { count: @value }) - matcher - end + @_submatchers ||= NumericalityMatchers::Submatchers.new(build_submatchers) end - def submatchers_and_results - @_submatchers_and_results ||= submatchers.map do |matcher| - { matcher: matcher, matched: matcher.matches?(@subject) } + private + + def build_submatchers + comparison_combos.map do |diff, submatcher_method_name| + matcher = __send__(submatcher_method_name, diff, nil) + matcher.with_message(@message, values: { count: @value }) + matcher end end diff --git a/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb b/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb index 33f5defce..055829f57 100644 --- a/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +++ b/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb @@ -55,11 +55,9 @@ def disallowed_value private def disallow_value_matcher - @_disallow_value_matcher ||= begin - DisallowValueMatcher.new(disallowed_value).tap do |matcher| - matcher.for(attribute) - wrap_disallow_value_matcher(matcher) - end + @_disallow_value_matcher ||= DisallowValueMatcher.new(disallowed_value).tap do |matcher| + matcher.for(attribute) + wrap_disallow_value_matcher(matcher) end end end diff --git a/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb b/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb new file mode 100644 index 000000000..03d823cd8 --- /dev/null +++ b/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb @@ -0,0 +1,71 @@ +require 'active_support/core_ext/module/delegation' + +module Shoulda + module Matchers + module ActiveModel + module NumericalityMatchers + # @private + class RangeMatcher < ValidationMatcher + OPERATORS = [:>=, :<=].freeze + + delegate :failure_message, to: :submatchers + + def initialize(numericality_matcher, attribute, range) + super(attribute) + unless numericality_matcher.respond_to? :diff_to_compare + raise ArgumentError, 'numericality_matcher is invalid' + end + + @numericality_matcher = numericality_matcher + @range = range + @attribute = attribute + end + + def matches?(subject) + @subject = subject + submatchers.matches?(subject) + end + + def simple_description + description = '' + + if expects_strict? + description << ' strictly' + end + + description + + "disallow :#{attribute} from being a number that is not " + + range_description + end + + def range_description + "from #{Shoulda::Matchers::Util.inspect_range(@range)}" + end + + def submatchers + @_submatchers ||= NumericalityMatchers::Submatchers.new(build_submatchers) + end + + private + + def build_submatchers + submatcher_combos.map do |value, operator| + build_comparison_submatcher(value, operator) + end + end + + def submatcher_combos + @range.minmax.zip(OPERATORS) + end + + def build_comparison_submatcher(value, operator) + NumericalityMatchers::ComparisonMatcher.new(@numericality_matcher, value, operator). + for(@attribute). + with_message(@message). + on(@context) + end + end + end + end + end +end diff --git a/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb b/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb new file mode 100644 index 000000000..c7d0a9d63 --- /dev/null +++ b/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb @@ -0,0 +1,43 @@ +module Shoulda + module Matchers + module ActiveModel + module NumericalityMatchers + # @private + class Submatchers + def initialize(submatchers) + @submatchers = submatchers + end + + def matches?(subject) + @subject = subject + failing_submatchers.empty? + end + + def failure_message + last_failing_submatcher.failure_message + end + + def failure_message_when_negated + last_failing_submatcher.failure_message_when_negated + end + + def add(submatcher) + @submatchers << submatcher + end + + def last_failing_submatcher + failing_submatchers.last + end + + private + + def failing_submatchers + @_failing_submatchers ||= @submatchers.reject do |submatcher| + submatcher.matches?(@subject) + end + end + end + end + end + end +end diff --git a/lib/shoulda/matchers/active_model/qualifiers.rb b/lib/shoulda/matchers/active_model/qualifiers.rb index 7af3d448a..f2090d8e8 100644 --- a/lib/shoulda/matchers/active_model/qualifiers.rb +++ b/lib/shoulda/matchers/active_model/qualifiers.rb @@ -9,5 +9,6 @@ module Qualifiers end require_relative 'qualifiers/allow_nil' +require_relative 'qualifiers/allow_blank' require_relative 'qualifiers/ignore_interference_by_writer' require_relative 'qualifiers/ignoring_interference_by_writer' diff --git a/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb b/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb new file mode 100644 index 000000000..9dc58a920 --- /dev/null +++ b/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb @@ -0,0 +1,26 @@ +module Shoulda + module Matchers + module ActiveModel + module Qualifiers + # @private + module AllowBlank + def initialize(*args) + super + @expects_to_allow_blank = false + end + + def allow_blank + @expects_to_allow_blank = true + self + end + + protected + + def expects_to_allow_blank? + @expects_to_allow_blank + end + end + end + end + end +end diff --git a/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb index 7a89baff4..a44d233b7 100644 --- a/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +++ b/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb @@ -108,7 +108,9 @@ def value obj end elsif array_column? - ['an arbitary value'] + ['an arbitrary value'] + elsif enum_column? + enum_values.first else case column_type when :integer, :float then 1 @@ -116,6 +118,7 @@ def value when :datetime, :time, :timestamp then Time.current when :date then Date.new when :binary then '0' + when :uuid then SecureRandom.uuid else 'an arbitrary value' end end @@ -145,6 +148,15 @@ def array_column? @subject.class.columns_hash[@attribute.to_s].respond_to?(:array) && @subject.class.columns_hash[@attribute.to_s].array end + + def enum_column? + @subject.class.respond_to?(:defined_enums) && + @subject.class.defined_enums.key?(@attribute.to_s) + end + + def enum_values + @subject.class.defined_enums[@attribute.to_s].values + end end end end diff --git a/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb index f7e6db2eb..5759308cf 100644 --- a/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +++ b/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb @@ -33,9 +33,9 @@ module ActiveModel # # class Game # include ActiveModel::Model - # attr_accessor :supported_os + # attr_accessor :floors_with_enemies # - # validates_exclusion_of :supported_os, in: 5..8 + # validates_exclusion_of :floors_with_enemies, in: 5..8 # end # # # RSpec diff --git a/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb index a9cb32fdb..f6a96298f 100644 --- a/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +++ b/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb @@ -3,6 +3,8 @@ module Shoulda module Matchers + class ExampleClass; end + module ActiveModel # The `validate_inclusion_of` matcher tests usage of the # `validates_inclusion_of` validation, asserting that an attribute can @@ -43,12 +45,12 @@ module ActiveModel # # # RSpec # RSpec.describe Issue, type: :model do - # it { should validate_inclusion_of(:state).in_range(1..5) } + # it { should validate_inclusion_of(:priority).in_range(1..5) } # end # # # Minitest (Shoulda) # class IssueTest < ActiveSupport::TestCase - # should validate_inclusion_of(:state).in_range(1..5) + # should validate_inclusion_of(:priority).in_range(1..5) # end # # #### Caveats @@ -269,7 +271,7 @@ def validate_inclusion_of(attr) # @private class ValidateInclusionOfMatcher < ValidationMatcher BLANK_VALUES = ['', ' ', "\n", "\r", "\t", "\f"].freeze - ARBITRARY_OUTSIDE_STRING = 'shoulda-matchers test string'.freeze + ARBITRARY_OUTSIDE_STRING = Shoulda::Matchers::ExampleClass.name ARBITRARY_OUTSIDE_INTEGER = 123456789 ARBITRARY_OUTSIDE_DECIMAL = BigDecimal('0.123456789') ARBITRARY_OUTSIDE_DATE = Date.jd(9999999) diff --git a/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb index 84480743d..7dcfb40c4 100644 --- a/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +++ b/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb @@ -239,7 +239,7 @@ module ActiveModel # # @return [ValidateLengthOfMatcher] # - # # ##### allow_blank + # ##### allow_blank # # Use `allow_blank` to assert that the attribute allows blank. # diff --git a/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb index 1b2c446fe..f10834e52 100644 --- a/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +++ b/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb @@ -276,6 +276,33 @@ module ActiveModel # should validate_numericality_of(:birth_day).odd # end # + # ##### is_in + # + # Use `is_in` to test usage of the `:in` option. + # This asserts that the attribute can take a number which is contained + # in the given range. + # + # class Person + # include ActiveModel::Model + # attr_accessor :legal_age + # + # validates_numericality_of :birth_month, in: 1..12 + # end + # + # # RSpec + # RSpec.describe Person, type: :model do + # it do + # should validate_numericality_of(:birth_month). + # is_in(1..12) + # end + # end + # + # # Minitest (Shoulda) + # class PersonTest < ActiveSupport::TestCase + # should validate_numericality_of(:birth_month). + # is_in(1..12) + # end + # # ##### with_message # # Use `with_message` if you are using a custom validation message. @@ -426,6 +453,13 @@ def is_other_than(value) self end + def is_in(range) + prepare_submatcher( + NumericalityMatchers::RangeMatcher.new(self, @attribute, range), + ) + self + end + def with_message(message) @expects_custom_validation_message = true @expected_message = message @@ -457,6 +491,10 @@ def simple_description description << "validate that :#{@attribute} looks like " description << Shoulda::Matchers::Util.a_or_an(full_allowed_type) + if range_description.present? + description << " #{range_description}" + end + if comparison_descriptions.present? description << " #{comparison_descriptions}" end @@ -673,6 +711,14 @@ def submatcher_comparison_descriptions end end + def range_description + range_submatcher = @submatchers.detect do |submatcher| + submatcher.respond_to? :range_description + end + + range_submatcher&.range_description + end + def model @subject.class end diff --git a/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb index c23302091..9b047e7a8 100644 --- a/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +++ b/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb @@ -78,6 +78,27 @@ module ActiveModel # should validate_presence_of(:nickname).allow_nil # end # + # #### allow_blank + # + # Use `allow_blank` to assert that the attribute allows blank. + # + # class Robot + # include ActiveModel::Model + # attr_accessor :nickname + # + # validates_presence_of :nickname, allow_blank: true + # end + # + # # RSpec + # RSpec.describe Robot, type: :model do + # it { should validate_presence_of(:nickname).allow_blank } + # end + # + # # Minitest (Shoulda) + # class RobotTest < ActiveSupport::TestCase + # should validate_presence_of(:nickname).allow_blank + # end + # # ##### on # # Use `on` if your validation applies only under a certain context. @@ -133,6 +154,7 @@ def validate_presence_of(attr) # @private class ValidatePresenceOfMatcher < ValidationMatcher include Qualifiers::AllowNil + include Qualifiers::AllowBlank def initialize(attribute) super @@ -144,7 +166,8 @@ def matches?(subject) possibly_ignore_interference_by_writer - if secure_password_being_validated? + if secure_password_being_validated? && + Shoulda::Matchers::RailsShim.active_model_lt_7? ignore_interference_by_writer.default_to(when: :blank?) disallowed_values.all? do |value| @@ -152,6 +175,7 @@ def matches?(subject) end else (!expects_to_allow_nil? || allows_value_of(nil)) && + (!expects_to_allow_blank? || allows_value_of('')) && disallowed_values.all? do |value| disallows_original_or_typecast_value?(value) end @@ -171,6 +195,7 @@ def does_not_match?(subject) end else (expects_to_allow_nil? && disallows_value_of(nil)) || + (expects_to_allow_blank? && disallows_value_of('')) || disallowed_values.any? do |value| allows_original_or_typecast_value?(value) end @@ -208,7 +233,7 @@ def secure_password_being_validated? end def possibly_ignore_interference_by_writer - if secure_password_being_validated? + if secure_password_being_validated? && RailsShim.active_model_lt_7? ignore_interference_by_writer.default_to(when: :blank?) end end @@ -241,11 +266,11 @@ def disallowed_values else values = [] - if attribute_accepts_string_values? + if attribute_accepts_string_values? && !expects_to_allow_blank? values << '' end - if !expects_to_allow_nil? + if !expects_to_allow_nil? && !expects_to_allow_blank? values << nil end diff --git a/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb b/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb index 361295c87..18379522a 100644 --- a/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +++ b/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb @@ -116,7 +116,7 @@ module ActiveRecord ## ##### with_prefix # # Use `with_prefix` to test that the enum is defined with a `_prefix` - # option (Rails 5 only). Can take either a boolean or a symbol: + # option (Rails 6+ only). Can take either a boolean or a symbol: # # class Issue < ActiveRecord::Base # enum status: [:open, :closed], _prefix: :old @@ -163,6 +163,30 @@ module ActiveRecord # with_suffix # end # + # ##### without_scopes + # + # Use `without_scopes` to test that the enum is defined with + # '_scopes: false' option (Rails 5 only). Can take either a boolean or a + # symbol: + # + # class Issue < ActiveRecord::Base + # enum status: [:open, :closed], _scopes: false + # end + # + # # RSpec + # RSpec.describe Issue, type: :model do + # it do + # should define_enum_for(:status). + # without_scopes + # end + # end + # + # # Minitest (Shoulda) + # class ProcessTest < ActiveSupport::TestCase + # should define_enum_for(:status). + # without_scopes + # end + # # @return [DefineEnumForMatcher] # def define_enum_for(attribute_name) @@ -173,7 +197,7 @@ def define_enum_for(attribute_name) class DefineEnumForMatcher def initialize(attribute_name) @attribute_name = attribute_name - @options = { expected_enum_values: [] } + @options = { expected_enum_values: [], scopes: true } end def description @@ -226,13 +250,19 @@ def backed_by_column_of_type(expected_column_type) self end + def without_scopes + options[:scopes] = false + self + end + def matches?(subject) @record = subject enum_defined? && enum_values_match? && column_type_matches? && - enum_value_methods_exist? + enum_value_methods_exist? && + scope_presence_matches? end def failure_message @@ -294,6 +324,10 @@ def expectation # rubocop:disable Metrics/MethodLength expectation << "_#{expected_suffix}".inspect end + if exclude_scopes? + expectation << ' with no scopes' + end + expectation else simple_description @@ -387,37 +421,81 @@ def model end def enum_value_methods_exist? - passed = expected_singleton_methods.all? do |method| - model.singleton_methods.include?(method) + if instance_methods_exist? + true + else + message = missing_methods_message + + message << " (we can't tell which)" + + @failure_message_continuation = message + + false end + end - if passed + def scope_presence_matches? + if exclude_scopes? + if singleton_methods_exist? + message = "#{attribute_name.inspect} does map to these values " + message << 'but class scope methods were present' + + @failure_message_continuation = message + + false + else + true + end + elsif singleton_methods_exist? true else - message = "#{attribute_name.inspect} does map to these " - message << 'values, but the enum is ' + if enum_defined? + message = 'But the class scope methods are not present' + else + message = missing_methods_message - if expected_prefix - if expected_suffix - message << 'configured with either a different prefix or ' - message << 'suffix, or no prefix or suffix at all' - else - message << 'configured with either a different prefix or no ' - message << 'prefix at all' - end - elsif expected_suffix - message << 'configured with either a different suffix or no ' - message << 'suffix at all' + message << 'or the class scope methods are not present' + message << " (we can't tell which)" end - message << " (we can't tell which)" - @failure_message_continuation = message false end end + def missing_methods_message + message = "#{attribute_name.inspect} does map to these " + message << 'values, but the enum is ' + + if expected_prefix + if expected_suffix + message << 'configured with either a different prefix or ' + message << 'suffix, or no prefix or suffix at all' + else + message << 'configured with either a different prefix or no ' + message << 'prefix at all' + end + elsif expected_suffix + message << 'configured with either a different suffix or no ' + message << 'suffix at all' + else + '' + end + end + + def singleton_methods_exist? + expected_singleton_methods.all? do |method| + model.singleton_methods.include?(method) + end + end + + def instance_methods_exist? + expected_instance_methods.all? do |method| + record.methods.include?(method) + end + end + def expected_singleton_methods expected_enum_value_names.map do |name| [expected_prefix, name, expected_suffix]. @@ -427,6 +505,18 @@ def expected_singleton_methods end end + def expected_instance_methods + methods = expected_enum_value_names.map do |name| + [expected_prefix, name, expected_suffix]. + select(&:present?). + join('_') + end + + methods.flat_map do |m| + ["#{m}?".to_sym, "#{m}!".to_sym] + end + end + def expected_prefix if options.include?(:prefix) if options[:prefix] == true @@ -447,6 +537,10 @@ def expected_suffix end end + def exclude_scopes? + !options[:scopes] + end + def to_hash(value) if value.is_a?(Array) value.each_with_index.inject({}) do |hash, (item, index)| diff --git a/lib/shoulda/matchers/active_record/have_db_column_matcher.rb b/lib/shoulda/matchers/active_record/have_db_column_matcher.rb index 5fc8911b8..5e47d2b11 100644 --- a/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +++ b/lib/shoulda/matchers/active_record/have_db_column_matcher.rb @@ -52,7 +52,7 @@ module ActiveRecord # # Use `with_options` to assert that a column has been defined with # certain options (`:precision`, `:limit`, `:default`, `:null`, `:scale`, - # or `:primary`). + # `:primary` or `:array`). # # class CreatePhones < ActiveRecord::Migration # def change @@ -84,7 +84,7 @@ def have_db_column(column) # @private class HaveDbColumnMatcher - OPTIONS = %i(precision limit default null scale primary).freeze + OPTIONS = %i(precision limit default null scale primary array).freeze def initialize(column) @column = column @@ -115,7 +115,8 @@ def matches?(subject) correct_default? && correct_null? && correct_scale? && - correct_primary? + correct_primary? && + correct_array? end def failure_message @@ -258,6 +259,23 @@ def correct_primary? end end + def correct_array? + return true unless @options.key?(:array) + + if matched_column.array? == @options[:array] + true + else + @missing = "#{model_class} has a db column named #{@column} " + @missing << + if @options[:primary] + 'that is not array, but should be' + else + 'that is array, but should not be' + end + false + end + end + def matched_column @_matched_column ||= begin column = model_class.columns.detect do |each| diff --git a/lib/shoulda/matchers/rails_shim.rb b/lib/shoulda/matchers/rails_shim.rb index 2474d7363..a68d64290 100644 --- a/lib/shoulda/matchers/rails_shim.rb +++ b/lib/shoulda/matchers/rails_shim.rb @@ -19,6 +19,20 @@ def active_record_version Gem::Version.new('0') end + def active_model_version + Gem::Version.new(::ActiveModel::VERSION::STRING) + rescue NameError + Gem::Version.new('0') + end + + def active_model_st_6_1? + Gem::Requirement.new('< 6.1').satisfied_by?(active_model_version) + end + + def active_model_lt_7? + Gem::Requirement.new('< 7').satisfied_by?(active_model_version) + end + def generate_validation_message( record, attribute, diff --git a/lib/shoulda/matchers/util/word_wrap.rb b/lib/shoulda/matchers/util/word_wrap.rb index f51e5cced..664b619fa 100644 --- a/lib/shoulda/matchers/util/word_wrap.rb +++ b/lib/shoulda/matchers/util/word_wrap.rb @@ -92,7 +92,7 @@ def combine_list_item_lines(lines) if line.list_item? combined_lines << line else - combined_lines.last << (" #{line}").squeeze(' ') + combined_lines.last << " #{line}".squeeze(' ') end combined_lines diff --git a/lib/shoulda/matchers/version.rb b/lib/shoulda/matchers/version.rb index 4b50d7f08..d5c54d3ff 100644 --- a/lib/shoulda/matchers/version.rb +++ b/lib/shoulda/matchers/version.rb @@ -1,6 +1,6 @@ module Shoulda module Matchers # @private - VERSION = '5.0.0'.freeze + VERSION = '5.3.0'.freeze end end diff --git a/shoulda-matchers.gemspec b/shoulda-matchers.gemspec index f7b73b803..0a61bff31 100644 --- a/shoulda-matchers.gemspec +++ b/shoulda-matchers.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |s| s.metadata = { 'bug_tracker_uri' => 'https://github.com/thoughtbot/shoulda-matchers/issues', - 'changelog_uri' => 'https://github.com/thoughtbot/shoulda-matchers/blob/master/CHANGELOG.md', + 'changelog_uri' => 'https://github.com/thoughtbot/shoulda-matchers/blob/main/CHANGELOG.md', 'documentation_uri' => 'https://matchers.shoulda.io/docs', 'homepage_uri' => 'https://matchers.shoulda.io', 'source_code_uri' => 'https://github.com/thoughtbot/shoulda-matchers', diff --git a/spec/support/acceptance/helpers/command_helpers.rb b/spec/support/acceptance/helpers/command_helpers.rb index f833a6fef..a19af56e1 100644 --- a/spec/support/acceptance/helpers/command_helpers.rb +++ b/spec/support/acceptance/helpers/command_helpers.rb @@ -23,7 +23,7 @@ def run_command!(*args) def run_command_isolated_from_bundle(*args) run_command(*args) do |runner| runner.around_command do |run_command| - Bundler.with_clean_env(&run_command) + Bundler.with_original_env(&run_command) end yield runner if block_given? diff --git a/spec/support/acceptance/helpers/rails_version_helpers.rb b/spec/support/acceptance/helpers/rails_version_helpers.rb index 1cd24bd3a..dcc2ff514 100644 --- a/spec/support/acceptance/helpers/rails_version_helpers.rb +++ b/spec/support/acceptance/helpers/rails_version_helpers.rb @@ -11,5 +11,9 @@ def rails_version def rails_gt_6_0? rails_version > 6.0 end + + def rails_6_x? + rails_version =~ '~> 6.0' + end end end diff --git a/spec/support/acceptance/helpers/ruby_version_helpers.rb b/spec/support/acceptance/helpers/ruby_version_helpers.rb index 8725944bf..a7f73dd63 100644 --- a/spec/support/acceptance/helpers/ruby_version_helpers.rb +++ b/spec/support/acceptance/helpers/ruby_version_helpers.rb @@ -5,5 +5,9 @@ module RubyVersionHelpers def ruby_version Tests::Version.new(RUBY_VERSION) end + + def ruby_gt_3_1? + ruby_version >= '3.1' + end end end diff --git a/spec/support/acceptance/helpers/step_helpers.rb b/spec/support/acceptance/helpers/step_helpers.rb index fa972ecf4..73a5b3250 100644 --- a/spec/support/acceptance/helpers/step_helpers.rb +++ b/spec/support/acceptance/helpers/step_helpers.rb @@ -23,11 +23,7 @@ def create_active_record_project add_gem 'activerecord', active_record_version add_gem 'rake' - if rails_version =~ '~> 6.0' - add_gem 'sqlite3', '~>1.4' - else - add_gem 'sqlite3', '~>1.3.6' - end + add_gem 'sqlite3', '~>1.4' end def create_generic_bundler_project @@ -86,16 +82,18 @@ def create_rails_application bundle.remove_gem 'web-console' end + add_gem 'net-smtp', require: false if rails_6_x? && ruby_gt_3_1? + fs.open('config/database.yml', 'w') do |file| YAML.dump(database.config.load_file, file) end end def rails_new_command - if rails_version =~ '~> 6.0' - "bundle exec rails new #{fs.project_directory} --database=#{database.adapter_name} --skip-bundle --skip-javascript --no-rc" + if rails_version >= 6.0 + "bundle exec rails new #{fs.project_directory} --database=#{database.adapter_name} --skip-bundle --skip-javascript --no-rc --skip-bootsnap" else - "bundle exec rails new #{fs.project_directory} --database=#{database.adapter_name} --skip-bundle --no-rc" + "bundle exec rails new #{fs.project_directory} --database=#{database.adapter_name} --skip-bundle --no-rc --skip-bootsnap" end end @@ -118,7 +116,7 @@ def add_rspec_to_project def add_rspec_rails_to_project! add_gem 'rspec-rails', rspec_rails_version - run_command_within_bundle!('bundle install --binstubs') if rails_gt_6_0? + run_command_within_bundle!('bundle install --local --binstubs') if rails_gt_6_0? run_command_within_bundle!('rails g rspec:install') remove_from_file '.rspec', '--warnings' end diff --git a/spec/support/tests/database_configuration.rb b/spec/support/tests/database_configuration.rb index 71d4ed4fc..626af33a7 100644 --- a/spec/support/tests/database_configuration.rb +++ b/spec/support/tests/database_configuration.rb @@ -17,6 +17,8 @@ def initialize(config) end def load_file + YAML::load_file(File.join(__dir__, "database_adapters/config/#{adapter}.yml"), aliases: true) + rescue ArgumentError YAML::load_file(File.join(__dir__, "database_adapters/config/#{adapter}.yml")) end end diff --git a/spec/support/unit/helpers/class_builder.rb b/spec/support/unit/helpers/class_builder.rb index c7e294b86..569aca74d 100644 --- a/spec/support/unit/helpers/class_builder.rb +++ b/spec/support/unit/helpers/class_builder.rb @@ -34,7 +34,7 @@ module #{namespace}::#{name_without_namespace} RUBY namespace.const_get(name_without_namespace).tap do |constant| - constant.unloadable + constant.unloadable if constant.respond_to?(:unloadable) # if Rails is in classic mode, mark it unloadable @_defined_modules = defined_modules | [constant] if block @@ -55,7 +55,7 @@ class #{namespace}::#{name_without_namespace} < ::#{parent_class} RUBY namespace.const_get(name_without_namespace).tap do |constant| - constant.unloadable + constant.unloadable if constant.respond_to?(:unloadable) # if Rails is in classic mode, mark it unloadable @_defined_modules = defined_modules | [constant] if block diff --git a/spec/support/unit/helpers/rails_versions.rb b/spec/support/unit/helpers/rails_versions.rb index e7831c24c..44ac3f59b 100644 --- a/spec/support/unit/helpers/rails_versions.rb +++ b/spec/support/unit/helpers/rails_versions.rb @@ -10,5 +10,9 @@ def self.configure_example_group(example_group) def rails_version Tests::Version.new(Rails::VERSION::STRING) end + + def rails_oldest_version_supported + 5.2 + end end end diff --git a/spec/support/unit/model_creation_strategies/active_model.rb b/spec/support/unit/model_creation_strategies/active_model.rb index 163356a9a..dda3e470d 100644 --- a/spec/support/unit/model_creation_strategies/active_model.rb +++ b/spec/support/unit/model_creation_strategies/active_model.rb @@ -104,7 +104,7 @@ def initialize(attributes = {}) end def inspect - middle = '%s:0x%014x%s' % [ # rubocop:disable Style/FormatStringToken + middle = '%s:0x%014x%s' % [ self.class, object_id * 2, " #{inspected_attributes.join(' ')}", diff --git a/spec/support/unit/rails_application.rb b/spec/support/unit/rails_application.rb index b55b12cee..b370b87d9 100644 --- a/spec/support/unit/rails_application.rb +++ b/spec/support/unit/rails_application.rb @@ -26,7 +26,8 @@ def create def load load_environment - add_action_text_migration if bundle.includes?('actiontext') + add_active_storage_migration + add_action_text_migration if rails_version >= 6.0 run_migrations end @@ -77,7 +78,6 @@ def temp_view_path_for(path) def generate rails_new fix_available_locales_warning - remove_bootsnap write_database_configuration write_activerecord_model_with_default_connection write_activerecord_model_with_different_connection @@ -90,25 +90,10 @@ def rails_new end def rails_new_command - if rails_version > 5 - [ - 'rails', - 'new', - fs.project_directory.to_s, - "--database=#{database.adapter_name}", - '--skip-bundle', - '--no-rc', - '--skip-webpack-install', - ] + if rails_version >= 6.0 + "bundle exec rails new #{fs.project_directory} --database=#{database.adapter_name} --skip-bundle --skip-javascript --no-rc --skip-bootsnap" else - [ - 'rails', - 'new', - fs.project_directory.to_s, - "--database=#{database.adapter_name}", - '--skip-bundle', - '--no-rc', - ] + "bundle exec rails new #{fs.project_directory} --database=#{database.adapter_name} --skip-bundle --no-rc --skip-bootsnap" end end @@ -124,18 +109,10 @@ def fix_available_locales_warning end end - def remove_bootsnap - # Rails 5.2 introduced bootsnap, which is helpful when you're developing - # or deploying an app, but we don't really need it (and it messes with - # Zeus anyhow) - fs.comment_lines_matching( - 'config/boot.rb', - %r{\Arequire 'bootsnap/setup'}, - ) - end - def write_database_configuration - YAML.dump(database.config.load_file, fs.open('config/database.yml', 'w')) + fs.open('config/database.yml', 'w') do |file| + YAML.dump(database.config.load_file, file) + end end def write_activerecord_model_with_different_connection @@ -174,6 +151,12 @@ def add_action_text_migration end end + def add_active_storage_migration + fs.within_project do + run_command! 'bundle exec rake active_storage:install:migrations' + end + end + def add_initializer_for_time_zone_aware_types path = 'config/initializers/configure_time_zone_aware_types.rb' fs.write(path, <<-TEXT) @@ -189,7 +172,11 @@ def load_environment def run_migrations fs.within_project do - run_command! 'bundle exec rake db:drop:all db:create:all db:migrate' + run_command! 'bundle exec rake db:drop:all db:create:all' + end + + fs.within_project do + run_command! 'bundle exec rake db:migrate' end end diff --git a/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb b/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb index 673812fcb..aa6d259aa 100644 --- a/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb @@ -14,6 +14,7 @@ def self.available_column_types :time, :date, :binary, + :uuid, ] end @@ -91,6 +92,15 @@ def self.available_column_types end end + context 'when the column backing the attribute is an enum' do + it 'still works' do + model = define_model_validating_absence_of(:attr) + model.enum attr: %w[one two three] + + expect(model.new).to validate_absence_of(:attr) + end + end + context 'when used in the negative' do it 'fails' do assertion = lambda do diff --git a/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb b/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb index 80599530c..3bffc3303 100644 --- a/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb @@ -145,7 +145,7 @@ def validation_matcher_scenario_args end context 'against a datetime attribute' do - now = DateTime.now + now = DateTime.new(2022, 1, 1) define_method(:now) { now } @@ -785,8 +785,7 @@ def configure_validation_matcher(matcher) include_context 'for a generic attribute' context 'against a timestamp column' do - now = DateTime.now - + now = DateTime.new(2022, 1, 1) define_method(:now) { now } it_behaves_like 'it supports in_array', @@ -887,6 +886,41 @@ def define_simple_model( def validation_matcher_scenario_args super.deep_merge(model_creator: :active_record) end + + context 'against a polymorphic association' do + it 'matches when the subject configures validate_inclusion_of' do + define_model(:issue, severity_id: :integer, severity_type: :string) do + belongs_to :severity, polymorphic: true + validates_inclusion_of :severity_type, in: %w(Low Medium High) + end + define_model(:high) + define_model(:medium) + define_model(:low) + + expect { validate_inclusion_of(:severity_type).in_array(%w(Low Medium High)) }.to match_against(Issue.new) + end + + it 'does not match when subject does not set validate_inclusion_of' do + define_model(:issue, severity_id: :integer, severity_type: :string) do + belongs_to :severity, polymorphic: true + end + define_model(:high) + define_model(:medium) + define_model(:low) + + expected_message = <<-MESSAGE.strip +Expected Issue to validate that :severity_type is either ‹"Low"›, +‹"Medium"›, or ‹"High"›, but this could not be proved. + After setting :severity_type to ‹"Shoulda::Matchers::ExampleClass"›, + the matcher expected the Issue to be invalid, but it was valid + instead. + MESSAGE + + expect { validate_inclusion_of(:severity_type).in_array(%w(Low Medium High)) }. + not_to match_against(Issue.new). + and_fail_with(expected_message) + end + end end context 'for a plain Ruby attribute' do diff --git a/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb b/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb index d1d5c6d44..92dfb2dbe 100644 --- a/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb @@ -69,26 +69,34 @@ def all_qualifiers # rubocop:disable Metrics/MethodLength validation_name: :on, validation_value: :customizable, }, + { + category: :range, + name: :is_in, + argument: 1..10, + validation_name: :in, + validation_value: 1..10, + rails_version: 7.0, + }, ] end def qualifiers_under(category) - all_qualifiers.select do |qualifier| + all_available_qualifiers.select do |qualifier| qualifier[:category] == category end end def mutually_exclusive_qualifiers - qualifiers_under(:cardinality) + qualifiers_under(:comparison) + qualifiers_under(:cardinality) + qualifiers_under(:comparison) + qualifiers_under(:range) end def non_mutually_exclusive_qualifiers - all_qualifiers - mutually_exclusive_qualifiers + all_available_qualifiers - mutually_exclusive_qualifiers end - def validations_by_qualifier - all_qualifiers.each_with_object({}) do |qualifier, hash| - hash[qualifier[:name]] = qualifier[:validation_name] + def all_available_qualifiers + all_qualifiers.filter do |qualifier| + rails_version >= qualifier.fetch(:rails_version, rails_oldest_version_supported) end end @@ -2065,6 +2073,144 @@ def validation_matcher_scenario_args end end + if rails_version >= 7.0 + context 'qualified with in' do + context 'validating with in' do + it 'accepts' do + record = build_record_validating_numericality( + in: 1..10, + ) + expect(record).to validate_numericality.is_in(1..10) + end + + it 'rejects when used in the negative' do + record = build_record_validating_numericality( + in: 1..10, + ) + + assertion = lambda do + expect(record).not_to validate_numericality.is_in(1..10) + end + + expect(&assertion).to fail_with_message(<<~MESSAGE) + Expected Example not to validate that :attr looks like a number from ‹1› + to ‹10›, but this could not be proved. + After setting :attr to ‹"abcd"›, the matcher expected the Example to + be valid, but it was invalid instead, producing these validation + errors: + + * attr: ["is not a number"] + MESSAGE + end + + it_supports( + 'ignoring_interference_by_writer', + tests: { + reject_if_qualified_but_changing_value_interferes: { + model_name: 'Example', + attribute_name: :attr, + changing_values_with: :next_value, + expected_message: <<-MESSAGE.strip, +Expected Example to validate that :attr looks like a number from ‹1› to +‹10›, but this could not be proved. + After setting :attr to ‹"10"› -- which was read back as ‹"11"› -- the + matcher expected the Example to be valid, but it was invalid instead, + producing these validation errors: + + * attr: ["must be in 1..10"] + + As indicated in the message above, :attr seems to be changing certain + values as they are set, and this could have something to do with why + this test is failing. If you've overridden the writer method for this + attribute, then you may need to change it to make this test pass, or + do something else entirely. + MESSAGE + }, + }, + ) do + def validation_matcher_scenario_args + super.deep_merge( + validation_options: { in: 1..10 }, + ) + end + + def configure_validation_matcher(matcher) + matcher.is_in(1..10) + end + end + + context 'when the attribute is a virtual attribute in an ActiveRecord model' do + it 'accepts' do + record = build_record_validating_numericality_of_virtual_attribute( + in: 1..10, + ) + expect(record).to validate_numericality. + is_in(1..10) + end + end + + context 'when the column is an integer column' do + it 'accepts (and does not raise an error)' do + record = build_record_validating_numericality( + column_type: :integer, + in: 1..10, + ) + + expect(record). + to validate_numericality. + is_in(1..10) + end + end + + context 'when the column is a float column' do + it 'accepts (and does not raise an error)' do + record = build_record_validating_numericality( + column_type: :float, + in: 1..10, + ) + + expect(record). + to validate_numericality. + is_in(1..10) + end + end + + context 'when the column is a decimal column' do + it 'accepts (and does not raise an error)' do + record = build_record_validating_numericality( + column_type: :decimal, + in: 1..10, + ) + + expect(record). + to validate_numericality. + is_in(1..10) + end + end + end + + context 'not validating with in' do + it 'rejects since it does not disallow numbers that are not in the range specified' do + record = build_record_validating_numericality + + assertion = lambda do + expect(record).to validate_numericality. + is_in(1..10) + end + + message = <<-MESSAGE +Expected Example to validate that :attr looks like a number from ‹1› to +‹10›, but this could not be proved. + After setting :attr to ‹"11"›, the matcher expected the Example to be + invalid, but it was valid instead. + MESSAGE + + expect(&assertion).to fail_with_message(message) + end + end + end + end + def build_validation_options(args) combination = args.fetch(:for) @@ -2080,7 +2226,11 @@ def apply_qualifiers!(args) combination.each do |qualifier| args = self.class.default_qualifier_arguments.fetch(qualifier[:name]) - matcher.__send__(qualifier[:name], *args) + if args + matcher.__send__(qualifier[:name], args) + else + matcher.__send__(qualifier[:name]) + end end end diff --git a/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb b/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb index 818a57320..afa52e816 100644 --- a/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb @@ -860,22 +860,24 @@ def record_belonging_to( end context 'against a pre-set password in a model that has_secure_password' do - it 'raises a CouldNotSetPasswordError' do - user_class = define_model :user, password_digest: :string do - has_secure_password validations: false - validates_presence_of :password - end + if Shoulda::Matchers::RailsShim.active_model_st_6_1? + it 'raises a CouldNotSetPasswordError' do + user_class = define_model :user, password_digest: :string do + has_secure_password validations: false + validates_presence_of :password + end - user = user_class.new - user.password = 'something' + user = user_class.new + user.password = 'something' - assertion = lambda do - expect(user).to validate_presence_of(:password) - end + assertion = lambda do + expect(user).to validate_presence_of(:password) + end - expect(&assertion).to raise_error( - Shoulda::Matchers::ActiveModel::CouldNotSetPasswordError, - ) + expect(&assertion).to raise_error( + Shoulda::Matchers::ActiveModel::CouldNotSetPasswordError, + ) + end end end @@ -1005,6 +1007,82 @@ def foo=(_value) end end + context 'qualified with allow_blank' do + context 'when validating a model with a presence validator' do + context 'and it is specified with allow_blank: true' do + it 'matches in the positive' do + record = validating_presence(allow_blank: true) + expect(record).to matcher.allow_blank + end + + it 'does not match in the negative' do + record = validating_presence(allow_blank: true) + + assertion = -> { expect(record).not_to matcher.allow_blank } + + expect(&assertion).to fail_with_message(<<-MESSAGE) +Expected Example not to validate that :attr cannot be empty/falsy, but +this could not be proved. + After setting :attr to ‹""›, the matcher expected the Example to be + invalid, but it was valid instead. + MESSAGE + end + end + + context 'and it is not specified with allow_blank: true' do + it 'does not match in the positive' do + record = validating_presence + + assertion = lambda do + expect(record).to matcher.allow_blank + end + + message = <<-MESSAGE +Expected Example to validate that :attr cannot be empty/falsy, but this +could not be proved. + After setting :attr to ‹""›, the matcher expected the Example to be + valid, but it was invalid instead, producing these validation errors: + + * attr: ["can't be blank"] + MESSAGE + + expect(&assertion).to fail_with_message(message) + end + end + + it 'matches in the negative' do + record = validating_presence + + expect(record).not_to matcher.allow_blank + end + end + + context 'when validating a model without a presence validator' do + it 'matches in the positive' do + record = without_validating_presence + + expect(record).to matcher.allow_blank + end + + it 'does not match in the negative' do + record = without_validating_presence + + assertion = lambda do + expect(record).not_to matcher.allow_blank + end + + message = <<-MESSAGE +Expected Example not to validate that :attr cannot be empty/falsy, but +this could not be proved. + After setting :attr to ‹""›, the matcher expected the Example to be + invalid, but it was valid instead. + MESSAGE + + expect(&assertion).to fail_with_message(message) + end + end + end + def matcher validate_presence_of(:attr) end diff --git a/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb b/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb index 626728c42..8fac61732 100644 --- a/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb @@ -845,8 +845,7 @@ def belonging_to_non_existent_class(model_name, assoc_name, options = {}) it 'rejects an association that has the wrong :through option' do define_model :child - define_model :conception, child_id: :integer, - parent_id: :integer do + define_model :conception, child_id: :integer, parent_id: :integer do belongs_to :child end @@ -1183,7 +1182,7 @@ def having_many_non_existent_class(model_name, assoc_name, options = {}) it 'accepts a valid association with an :as option' do define_model :detail, detailable_id: :integer, - detailable_type: :string + detailable_type: :string define_model :person do has_one :detail, as: :detailable end @@ -1226,7 +1225,7 @@ def having_many_non_existent_class(model_name, assoc_name, options = {}) it 'rejects an association with a bad :as option' do define_model :detail, detailable_id: :integer, - detailable_type: :string + detailable_type: :string define_model :person do has_one :detail, as: :describable end @@ -1524,7 +1523,7 @@ def having_one_non_existent(model_name, assoc_name, options = {}) define_model :relative define_model :person define_model :people_relative, id: false, person_id: :integer, - relative_id: :integer + relative_id: :integer expect(Person.new).not_to have_and_belong_to_many(:relatives) end @@ -1980,7 +1979,7 @@ def having_one_non_existent(model_name, assoc_name, options = {}) define_association_with_conditions(model, :has_and_belongs_to_many, :relatives, adopted: true) end define_model :people_relative, id: false, person_id: :integer, - relative_id: :integer + relative_id: :integer expect(Person.new).to have_and_belong_to_many(:relatives).conditions(adopted: true) end @@ -1991,7 +1990,7 @@ def having_one_non_existent(model_name, assoc_name, options = {}) has_and_belongs_to_many :relatives end define_model :people_relative, id: false, person_id: :integer, - relative_id: :integer + relative_id: :integer expect(Person.new).not_to have_and_belong_to_many(:relatives).conditions(adopted: true) end @@ -2008,7 +2007,7 @@ def having_one_non_existent(model_name, assoc_name, options = {}) end define_model :people_person_relative, person_id: :integer, - person_relative_id: :integer + person_relative_id: :integer expect(Person.new).to have_and_belong_to_many(:relatives).class_name('PersonRelative') end @@ -2081,7 +2080,7 @@ def having_one_non_existent(model_name, assoc_name, options = {}) has_and_belongs_to_many :relatives, autosave: true end define_model :people_relative, person_id: :integer, - relative_id: :integer + relative_id: :integer expect(Person.new).to have_and_belong_to_many(:relatives).autosave(true) end @@ -2091,7 +2090,7 @@ def having_one_non_existent(model_name, assoc_name, options = {}) has_and_belongs_to_many :relatives end define_model :people_relative, person_id: :integer, - relative_id: :integer + relative_id: :integer message = 'Expected Person to have a has_and_belongs_to_many association called relatives (relatives should have autosave set to true)' expect { @@ -2124,7 +2123,7 @@ def having_one_non_existent(model_name, assoc_name, options = {}) def having_and_belonging_to_many_relatives(_options = {}) define_model :relative define_model :people_relative, id: false, person_id: :integer, - relative_id: :integer + relative_id: :integer define_model :person do has_and_belongs_to_many :relatives end.new diff --git a/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb b/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb index a589ef0fd..8e4190aeb 100644 --- a/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb @@ -807,6 +807,78 @@ def self.statuses end end + if rails_version =~ '~> 6.0' + context 'qualified with #without_scopes' do + context 'if scopes are set to false on the enum but without_scopes is not used' do + it 'has the right description' do + record = build_record_with_array_values( + attribute_name: :attr, + scopes: false, + ) + + matcher = lambda do + expect(record). + to define_enum_for(:attr). + with_values(['published', 'unpublished', 'draft']) + end + + message = format_message(<<-MESSAGE) + Expected Example to define :attr as an enum backed by an + integer, mapping ‹"published"› to ‹0›, ‹"unpublished"› to ‹1›, + and ‹"draft"› to ‹2›. But the class scope methods are not present. + MESSAGE + + expect(&matcher).to fail_with_message(message) + end + end + + context 'if scopes are set to false on the enum' do + it 'matches' do + record = build_record_with_array_values( + attribute_name: :attr, + scopes: false, + ) + + matcher = lambda do + define_enum_for(:attr). + with_values(['published', 'unpublished', 'draft']). + without_scopes + end + + expect(&matcher). + to match_against(record). + or_fail_with(<<-MESSAGE, wrap: true) + Expected Example not to define :attr as an enum backed by an + integer, mapping ‹"published"› to ‹0›, ‹"unpublished"› to ‹1›, + and ‹"draft"› to ‹2› with no scopes, but it did. + MESSAGE + end + end + + context 'if scopes are not set to false on the enum' do + it 'has the right description' do + record = build_record_with_array_values(attribute_name: :attr) + + matcher = lambda do + expect(record). + to define_enum_for(:attr). + with_values(['published', 'unpublished', 'draft']). + without_scopes + end + + message = format_message(<<-MESSAGE) + Expected Example to define :attr as an enum backed by an + integer, mapping ‹"published"› to ‹0›, ‹"unpublished"› to ‹1›, + and ‹"draft"› to ‹2› with no scopes. :attr does map to these + values but class scope methods were present. + MESSAGE + + expect(&matcher).to fail_with_message(message) + end + end + end + end + def build_record_with_array_values( model_name: 'Example', attribute_name: :attr, @@ -814,7 +886,8 @@ def build_record_with_array_values( values: ['published', 'unpublished', 'draft'], prefix: false, suffix: false, - attribute_alias: nil + attribute_alias: nil, + scopes: true ) build_record_with_enum_attribute( model_name: model_name, @@ -824,6 +897,7 @@ def build_record_with_array_values( prefix: prefix, suffix: suffix, attribute_alias: attribute_alias, + scopes: scopes, ) end @@ -832,7 +906,8 @@ def build_record_with_hash_values( attribute_name: :attr, values: { active: 0, archived: 1 }, prefix: false, - suffix: false + suffix: false, + scopes: true ) build_record_with_enum_attribute( model_name: model_name, @@ -841,6 +916,7 @@ def build_record_with_hash_values( values: values, prefix: prefix, suffix: suffix, + scopes: scopes, attribute_alias: nil, ) end @@ -851,6 +927,7 @@ def build_record_with_enum_attribute( column_type:, values:, attribute_alias:, + scopes: true, prefix: false, suffix: false ) @@ -862,7 +939,21 @@ def build_record_with_enum_attribute( alias_attribute attribute_alias, attribute_name end - model.enum(enum_name => values, _prefix: prefix, _suffix: suffix) + params = { + enum_name => values, + _prefix: prefix, + _suffix: suffix, + } + + if rails_version >= 7.0 + model.enum(enum_name, values, prefix: prefix, suffix: suffix) + else + if rails_version =~ '~> 6.0' + params.merge!(_scopes: scopes) + end + + model.enum(params) + end model.new end diff --git a/spec/unit/shoulda/matchers/active_record/have_attached_matcher_spec.rb b/spec/unit/shoulda/matchers/active_record/have_attached_matcher_spec.rb index db9cedaa3..3b3fec53a 100644 --- a/spec/unit/shoulda/matchers/active_record/have_attached_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_record/have_attached_matcher_spec.rb @@ -1,35 +1,6 @@ require 'unit_spec_helper' describe Shoulda::Matchers::ActiveRecord::HaveAttachedMatcher, type: :model do - before do - create_table :active_storage_blobs do |t| - t.string :key, null: false - t.string :filename, null: false - t.string :content_type - t.text :metadata - t.bigint :byte_size, null: false - t.string :checksum, null: false - t.datetime :created_at, null: false - - t.index [:key], unique: true - end - - create_table :active_storage_attachments do |t| - t.string :name, null: false - t.references :record, null: false, polymorphic: true, index: false - t.references :blob, null: false - - t.datetime :created_at, null: false - - t.index [:record_type, :record_id, :name, :blob_id], - name: 'index_active_storage_attachments_uniqueness', unique: true - - # The original rails migration has a foreign key. - # Since this messes up the clearing of the database, it's removed here. - # t.foreign_key :active_storage_blobs, column: :blob_id - end - end - describe 'have_one_attached' do describe '#description' do it 'returns the message with the name of the association' do diff --git a/spec/unit/shoulda/matchers/active_record/have_db_column_matcher_spec.rb b/spec/unit/shoulda/matchers/active_record/have_db_column_matcher_spec.rb index 47ae006ee..9b071b1fb 100644 --- a/spec/unit/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_record/have_db_column_matcher_spec.rb @@ -98,6 +98,20 @@ end end + if database_supports_array_columns? + context 'with array option' do + it 'accepts a column that is array' do + expect(with_table(:tags, :string, array: true)). + to have_db_column(:tags).with_options(array: true) + end + + it 'rejects a column that is not array' do + expect(with_table(:whatever, :string, array: false)). + not_to have_db_column(:whatever).with_options(array: true) + end + end + end + context 'with invalid argument option' do it 'raises an error with the unknown options' do expect {