From a9c1d9a11732b57e1b898e74516bbff36724ff97 Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Thu, 25 Apr 2024 17:17:56 +0700 Subject: [PATCH] Appraisal & Combustion; Rails 3, 6, & 7 Compat fixes (#105) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * πŸ§‘β€πŸ’» Default to No DEBUG=true * πŸ‘· Setup Appraisal * πŸ‘· Attempt to use custom RuboCop version * πŸ‘· Unspecify rubygems version for old Ruby + Rails combos * πŸ‘· Remove rubygems version for old Ruby + Rails combos * πŸ‘· Specify old bundler version for old Ruby + Rails combos * πŸ‘· Experimental true for finicky bundler/rubygems combos * 🚨 Lint lock * πŸ‘· RAILS_VERSION * πŸ‘· RAILS_MAJOR_MINOR * πŸ‘· Ancient Rails Support * πŸ‘· Fix names * πŸ’š Fix test * πŸ’š Fix test * πŸ’š Fix tests * πŸ’š Fix env variables * πŸ’š Fix env variables * πŸ’š Fix rdoc version * πŸ’š Allow JSON Version for Rails 4 support * πŸ’š consolidate on matrix.rails * ✨ Combustion Test Rails App * ✨ Combustion Testing * πŸ‘· Combustion Testing * πŸ’š Fix dependency version pins * πŸ’š Fix code coverage * πŸ”¨ Regenerate Appraisals * βž– Min branch cov = 72% * πŸ”§ Fix path to gemspec * βž– rspec-rails * βž– actionpack * βœ… Add back Rails 3.0-, 3.1, 3.2 * πŸ“Œ rake v10 for ancient Appraisals * πŸ“Œ tzinfo v1 for ancient Rails * πŸ“Œ delivery_method :test for Rails 3 * πŸ“Œ undefined method `unparsed_value' for # on Rails 3 * πŸ“Œ branch coverage @ 71% * πŸ“Œ undefined method `unparsed_value' for # on Rails 3 * πŸ’š Fix test on Rails 3 * πŸ’š Fix typo * 🚨 Lint lock * πŸ‘· Turn off experimental CI flags * πŸ‘· prefer block_is_expected * πŸ”₯ Remove bogus comment * πŸ”₯ Remove bogus comments * πŸ“ Improve documentation * 🚨 Disable RSpec/ExampleLength * πŸ“ Documentation * πŸ”§ 89% coverage * πŸ”– Prepare release v2.0.6 * 🚨 Lint lock * πŸ“ Improved documentation --- .envrc | 6 +- .github/workflows/ancient.yml | 82 +++++ .github/workflows/coverage.yml | 6 +- .github/workflows/heads.yml | 2 +- .github/workflows/legacy.yml | 136 ++++++-- .github/workflows/style.yml | 3 +- .github/workflows/supported.yml | 90 +++-- .hound.yml | 1 + .rspec | 2 +- .rubocop.yml | 3 + .rubocop_gradual.lock | 360 +++++++++----------- Appraisals | 190 ++++++++++- CHANGELOG.md | 20 +- CONTRIBUTING.md | 8 + Gemfile | 6 + Gemfile.lock | 94 +---- README.md | 15 +- config.ru | 9 + gemfiles/coverage.gemfile | 8 + gemfiles/rails_3_0.gemfile | 16 + gemfiles/rails_3_1.gemfile | 15 + gemfiles/rails_3_2.gemfile | 13 + gemfiles/rails_4_0.gemfile | 11 + gemfiles/rails_4_1.gemfile | 11 + gemfiles/rails_4_2.gemfile | 16 +- gemfiles/rails_5_0.gemfile | 15 +- gemfiles/rails_5_1.gemfile | 15 +- gemfiles/rails_5_2.gemfile | 15 +- gemfiles/rails_6_0.gemfile | 9 + gemfiles/rails_6_1.gemfile | 9 + gemfiles/rails_7_0.gemfile | 9 + gemfiles/rails_7_1.gemfile | 9 + gemfiles/style.gemfile | 8 + gemfiles/vanilla.gemfile | 5 + lib/sanitize_email.rb | 159 +++++---- lib/sanitize_email/engine_v5.rb | 1 + lib/sanitize_email/engine_v6.rb | 5 +- lib/sanitize_email/mail_ext.rb | 2 + lib/sanitize_email/overridden_addresses.rb | 9 +- lib/sanitize_email/railtie.rb | 1 + lib/sanitize_email/version.rb | 2 +- sanitize_email.gemspec | 9 +- spec/internal/app/assets/config/manifest.js | 0 spec/internal/config/database.yml | 3 + spec/internal/config/routes.rb | 5 + spec/internal/config/storage.yml | 3 + spec/internal/db/schema.rb | 6 + spec/internal/log/.gitignore | 1 + spec/internal/public/favicon.ico | 0 spec/rails_helper.rb | 25 ++ spec/rails_spec.rb | 14 + spec/sanitize_email_spec.rb | 91 +++-- spec/spec_helper.rb | 15 - 53 files changed, 1037 insertions(+), 531 deletions(-) create mode 100644 .github/workflows/ancient.yml create mode 100644 config.ru create mode 100644 gemfiles/rails_3_0.gemfile create mode 100644 gemfiles/rails_3_1.gemfile create mode 100644 gemfiles/rails_3_2.gemfile create mode 100644 gemfiles/rails_4_0.gemfile create mode 100644 gemfiles/rails_4_1.gemfile create mode 100644 gemfiles/rails_6_0.gemfile create mode 100644 gemfiles/rails_6_1.gemfile create mode 100644 gemfiles/rails_7_0.gemfile create mode 100644 gemfiles/rails_7_1.gemfile create mode 100644 spec/internal/app/assets/config/manifest.js create mode 100644 spec/internal/config/database.yml create mode 100644 spec/internal/config/routes.rb create mode 100644 spec/internal/config/storage.yml create mode 100644 spec/internal/db/schema.rb create mode 100644 spec/internal/log/.gitignore create mode 100644 spec/internal/public/favicon.ico create mode 100644 spec/rails_helper.rb create mode 100644 spec/rails_spec.rb diff --git a/.envrc b/.envrc index 35f9af0..53f01e9 100644 --- a/.envrc +++ b/.envrc @@ -1,9 +1,11 @@ ### External Testing Controls export K_SOUP_COV_DO=true # Means you want code coverage export K_SOUP_COV_MIN_BRANCH=71 # Means you want to enforce X% branch coverage -export K_SOUP_COV_MIN_LINE=90 # Means you want to enforce X% line coverage +export K_SOUP_COV_MIN_LINE=89 # Means you want to enforce X% line coverage export K_SOUP_COV_MIN_HARD=true # Means you want the build to fail if the coverage thresholds are not met # Available formats are html, xml, rcov, lcov, json, tty export K_SOUP_COV_MULTI_FORMATTERS="html,tty" # What coverage output formats do you want? export MAX_ROWS=5 # Setting for simplecov-console gem for tty output, limits to the worst N rows of bad coverage -export DEBUG=true # allow byebug statements +# export DEBUG=true # allow byebug statements +export RAILS_VERSION="~> 7.1" +export RAILS_MAJOR_MINOR=7.1 diff --git a/.github/workflows/ancient.yml b/.github/workflows/ancient.yml new file mode 100644 index 0000000..0d2b2c8 --- /dev/null +++ b/.github/workflows/ancient.yml @@ -0,0 +1,82 @@ +name: Rails 3 - 4.1 on EOL Ruby 2.3 + +on: + push: + branches: + - 'main' + - '*-stable' + - '*-dev' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Specs - Ruby ${{ matrix.ruby }} & Rails ${{ matrix.rails }} ${{ matrix.name_extra || '' }} + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + # rspec-rails uses RAILS_VERSION internally + RAILS_VERSION: "~> ${{ matrix.rails }}" + # Our spec suite (not runtime code) uses RAILS_MAJOR_MINOR internally + RAILS_MAJOR_MINOR: ${{ matrix.rails }} + strategy: + fail-fast: false + matrix: + include: + - ruby: "2.3" + appraisal: "rails-4-1" + bundler: '1.17.3' + gemfile: vanilla + rails: "4.1" + - ruby: "2.3" + appraisal: "rails-4-0" + bundler: '1.17.3' + gemfile: vanilla + rails: "4.0" + - ruby: "2.3" + appraisal: "rails-3-2" + bundler: '1.17.3' + gemfile: vanilla + rails: "3.2" + - ruby: "2.3" + appraisal: "rails-3-1" + bundler: '1.17.3' + gemfile: vanilla + rails: "3.1" + - ruby: "2.3" + appraisal: "rails-3-0" + bundler: '1.17.3' + gemfile: vanilla + rails: "3.0" + runs-on: ubuntu-20.04 + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + # This will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. vanilla) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the root Gemfile at all. + - name: Bundle for Appraisal ${{ matrix.appraisal }} (Rails v${{ matrix.rails}}) + run: bundle _1.17.3_ install + - name: Install Appraisal ${{ matrix.appraisal }} (Rails v${{ matrix.rails}}) dependencies + run: bundle _1.17.3_ exec appraisal ${{ matrix.appraisal }} bundle _1.17.3_ install + - name: Run tests ${{ matrix.appraisal }} (Rails v${{ matrix.rails}}) + run: bundle _1.17.3_ exec appraisal ${{ matrix.appraisal }} bundle _1.17.3_ exec rake test diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index c76f6b3..cf86b46 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -1,8 +1,8 @@ name: Ruby - Coverage env: - K_SOUP_COV_MIN_BRANCH: 73 - K_SOUP_COV_MIN_LINE: 90 + K_SOUP_COV_MIN_BRANCH: 71 + K_SOUP_COV_MIN_LINE: 89 K_SOUP_COV_MIN_HARD: true on: @@ -56,7 +56,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Setup Ruby & Bundle + - name: Setup Ruby & RubyGems uses: ruby/setup-ruby@v1 with: ruby-version: "${{ matrix.ruby }}" diff --git a/.github/workflows/heads.yml b/.github/workflows/heads.yml index 50e422b..74cbfb0 100644 --- a/.github/workflows/heads.yml +++ b/.github/workflows/heads.yml @@ -51,7 +51,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Setup Ruby & Bundle + - name: Setup Ruby & RubyGems uses: ruby/setup-ruby@v1 with: ruby-version: "${{ matrix.ruby }}" diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 67f2952..dc727ff 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -1,4 +1,4 @@ -name: Legacy Ruby Support +name: Rails 4.2, 5, 6, 7 on EOL Ruby 2.5 - 3.0 on: push: @@ -17,43 +17,137 @@ on: # Cancels all previous workflow runs for the same branch that have not yet completed. concurrency: # The concurrency group contains the workflow name and the branch name. - group: ${{ github.workflow }}-${{ github.ref }} + group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true jobs: test: - name: Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} + name: Specs - Ruby ${{ matrix.ruby }} & Rails ${{ matrix.rails }} ${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + # rspec-rails uses RAILS_VERSION internally + RAILS_VERSION: "~> ${{ matrix.rails }}" + # Our spec suite (not runtime code) uses RAILS_MAJOR_MINOR internally + RAILS_MAJOR_MINOR: ${{ matrix.rails }} strategy: fail-fast: false matrix: - experimental: [false] - rubygems: - - "2.7.11" - bundler: - - none - gemfile: - - vanilla - ruby: - - "3.0" - - "2.7" - - "2.6" - - "2.5" - - "2.4" - - "2.3" + include: + - ruby: "3.0" + appraisal: "rails-7-1" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "7.1" + - ruby: "3.0" + appraisal: "rails-7-0" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "7.0" + - ruby: "3.0" + appraisal: "rails-6-1" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "6.1" + - ruby: "2.7" + appraisal: "rails-7-1" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "7.1" + - ruby: "2.7" + appraisal: "rails-7-0" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "7.0" + - ruby: "2.7" + appraisal: "rails-6-1" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "6.1" + - ruby: "2.7" + appraisal: "rails-6-0" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "6.0" + - ruby: "2.7" + appraisal: "rails-5-2" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "5.2" + - ruby: "2.6" + appraisal: "rails-6-1" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "6.1" + - ruby: "2.6" + appraisal: "rails-6-0" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "6.0" + - ruby: "2.6" + appraisal: "rails-5-2" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "5.2" + - ruby: "2.5" + appraisal: "rails-6-1" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "6.1" + - ruby: "2.5" + appraisal: "rails-6-0" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "6.0" + - ruby: "2.5" + appraisal: "rails-5-2" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "5.2" + - ruby: "2.5" + appraisal: "rails-5-1" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "5.1" + - ruby: "2.5" + appraisal: "rails-4-2" + rubygems: "3.3.27" + bundler: none + gemfile: vanilla + rails: "4.2" runs-on: ubuntu-20.04 continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} steps: - name: Checkout uses: actions/checkout@v4 - - name: Setup Ruby & Bundle + - name: Setup Ruby & RubyGems uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} rubygems: ${{ matrix.rubygems }} bundler: ${{ matrix.bundler }} - bundler-cache: true - - name: Run tests - run: bundle exec rake test + bundler-cache: false + # This will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. vanilla) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the root Gemfile at all. + - name: Bundle for Appraisal ${{ matrix.appraisal }} (Rails v${{ matrix.rails}}) + run: bundle + - name: Install Appraisal ${{ matrix.appraisal }} (Rails v${{ matrix.rails}}) dependencies + run: bundle exec appraisal ${{ matrix.appraisal }} bundle + - name: Run tests ${{ matrix.appraisal }} (Rails v${{ matrix.rails}}) + run: bundle exec appraisal ${{ matrix.appraisal }} bundle exec rake test diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index 4896968..f23c301 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -22,7 +22,6 @@ jobs: strategy: fail-fast: false matrix: - experimental: [true] rubygems: - latest bundler: @@ -38,7 +37,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - name: Setup Ruby & Bundle + - name: Setup Ruby & RubyGems uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} diff --git a/.github/workflows/supported.yml b/.github/workflows/supported.yml index 1ad6841..5c43c53 100644 --- a/.github/workflows/supported.yml +++ b/.github/workflows/supported.yml @@ -1,4 +1,4 @@ -name: Ruby Current Matrix +name: Ruby & Rails Current Matrix env: K_SOUP_COV_DO: false @@ -28,37 +28,85 @@ concurrency: jobs: test: - name: Specs - Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} + name: Specs - Ruby ${{ matrix.ruby }} & Rails ${{ matrix.rails }} ${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + # rspec-rails uses RAILS_VERSION internally + RAILS_VERSION: "~> ${{ matrix.rails }}" + # Our spec suite (not runtime code) uses RAILS_MAJOR_MINOR internally + RAILS_MAJOR_MINOR: ${{ matrix.rails }} runs-on: ubuntu-latest strategy: matrix: - rubygems: - - latest - bundler: - - latest - gemfile: - - vanilla - ruby: - #- '3.1' - 3.1 tests are run by coverage.yml - - '3.2' - - '3.3' - - truffleruby - - jruby - + include: + - ruby: "3.3" + appraisal: "rails-7-1" + rubygems: latest + bundler: latest + gemfile: vanilla + rails: "7.1" + - ruby: "3.3" + appraisal: "rails-7-0" + rubygems: latest + bundler: latest + gemfile: vanilla + rails: "7.0" + - ruby: "3.2" + appraisal: "rails-7-1" + rubygems: latest + bundler: latest + gemfile: vanilla + rails: "7.1" + - ruby: "3.2" + appraisal: "rails-7-0" + rubygems: latest + bundler: latest + gemfile: vanilla + rails: "7.0" + #- '3.1' - Rails 7.1 on Ruby 3.1 tests are run by coverage.yml + - ruby: "3.1" + appraisal: "rails-7-0" + rubygems: latest + bundler: latest + gemfile: vanilla + rails: "7.0" + - ruby: "3.1" + appraisal: "rails-6-1" + rubygems: latest + bundler: latest + gemfile: vanilla + rails: "6.1" + - ruby: "truffleruby" + appraisal: "rails-7-1" + rubygems: latest + bundler: latest + gemfile: vanilla + rails: "7.1" + - ruby: "jruby" + appraisal: "rails-7-1" + rubygems: latest + bundler: latest + gemfile: vanilla + rails: "7.1" steps: - name: Checkout uses: actions/checkout@v4 - - - name: Setup Ruby & Bundle + - uses: actions/cache@v4 + id: cache + with: + path: path/to/dependencies + key: ${{ runner.os }}-${{matrix.ruby}}-${{matrix.appraisal}}-${{ hashFiles('gemfiles/*.gemfile.lock') }} + - name: Setup Ruby & RubyGems uses: ruby/setup-ruby@v1 with: ruby-version: "${{ matrix.ruby }}" rubygems: "${{ matrix.rubygems }}" bundler: "${{ matrix.bundler }}" - bundler-cache: true - - - name: Run tests - run: bundle exec rake test + bundler-cache: false + - name: Bundle for Appraisal ${{ matrix.appraisal }} (Rails v${{ matrix.rails}}) + run: bundle + - name: Install Appraisal ${{ matrix.appraisal }} (Rails v${{ matrix.rails}}) dependencies + run: bundle exec appraisal ${{ matrix.appraisal }} bundle + - name: Run tests ${{ matrix.appraisal }} (Rails v${{ matrix.rails}}) + run: bundle exec appraisal ${{ matrix.appraisal }} bundle exec rake test diff --git a/.hound.yml b/.hound.yml index f534df8..3ecf6bb 100644 --- a/.hound.yml +++ b/.hound.yml @@ -1,2 +1,3 @@ rubocop: config_file: .rubocop.yml + version: 1.62.1 diff --git a/.rspec b/.rspec index 2559e39..b97622f 100644 --- a/.rspec +++ b/.rspec @@ -1,3 +1,3 @@ --color --format progress ---require spec_helper +--require rails_helper diff --git a/.rubocop.yml b/.rubocop.yml index e836558..73500cf 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -3,3 +3,6 @@ inherit_gem: RSpec/InstanceVariable: Enabled: false + +RSpec/ExampleLength: + Enabled: false diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock index 81e3c4f..02c4e3e 100644 --- a/.rubocop_gradual.lock +++ b/.rubocop_gradual.lock @@ -1,6 +1,6 @@ { - "README.md:2827675023": [ - [502, 6, 1, "Lint/Syntax: unexpected token tCOMMA\n(Using Ruby 2.3 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 177545] + "README.md:2858832830": [ + [504, 6, 1, "Lint/Syntax: unexpected token tCOMMA\n(Using Ruby 2.3 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 177545] ], "Rakefile:687725157": [ [8, 3, 30, "Style/MethodCallWithArgsParentheses: Use parentheses for method calls with arguments.", 2786900295], @@ -10,17 +10,8 @@ "init.rb:3429808413": [ [3, 9, 16, "Style/StringLiterals: Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.", 29970817] ], - "lib/sanitize_email.rb:1771666431": [ - [51, 3, 110, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 244581949], - [56, 3, 67, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 4112587574], - [56, 3, 67, "Style/MissingRespondToMissing: When using `method_missing`, define `respond_to_missing?`.", 4112587574], - [62, 3, 148, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1610211115], - [68, 3, 87, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1634519225], - [72, 3, 141, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1031065844], - [78, 5, 29, "ThreadSafety/ClassAndModuleAttributes: Avoid mutating class and module attributes.", 1399760671], - [97, 3, 354, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2628092758], - [119, 3, 184, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2216955970], - [126, 3, 287, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1344355207] + "lib/sanitize_email.rb:3334182494": [ + [57, 5, 29, "ThreadSafety/ClassAndModuleAttributes: Avoid mutating class and module attributes.", 1399760671] ], "lib/sanitize_email/config.rb:393256477": [ [13, 7, 21, "ThreadSafety/ClassAndModuleAttributes: Avoid mutating class and module attributes.", 622027168], @@ -49,194 +40,161 @@ [65, 5, 233, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2880787383], [73, 5, 386, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1085137330] ], - "spec/sanitize_email_spec.rb:3508591302": [ + "spec/sanitize_email_spec.rb:4173540361": [ [7, 3, 280, "RSpec/LeakyConstantDeclaration: Stub constant instead of declaring explicitly.", 1223327], - [114, 15, 19, "RSpec/VariableName: Use snake_case for variable names.", 372347066], - [123, 15, 19, "RSpec/VariableName: Use snake_case for variable names.", 372347066], - [141, 15, 19, "RSpec/VariableName: Use snake_case for variable names.", 372347066], - [153, 15, 19, "RSpec/VariableName: Use snake_case for variable names.", 372347066], - [165, 15, 19, "RSpec/VariableName: Use snake_case for variable names.", 372347066], - [177, 15, 19, "RSpec/VariableName: Use snake_case for variable names.", 372347066], - [202, 11, 16, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 4266815955], - [205, 16, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], - [209, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], - [213, 16, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], - [213, 40, 2, "RSpec/BeEq: Prefer `be` over `eq`.", 5860785], - [219, 16, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], - [223, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], - [227, 16, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], - [227, 45, 2, "RSpec/BeEq: Prefer `be` over `eq`.", 5860785], - [233, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], - [239, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], - [243, 13, 12, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 491923605], - [249, 7, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [255, 7, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], - [255, 7, 250, "RSpec/ExampleLength: Example has too many lines. [6/5]", 245631994], - [264, 7, 19, "RSpec/MultipleExpectations: Example has too many expectations [9/1].", 2796689240], - [264, 7, 609, "RSpec/ExampleLength: Example has too many lines. [9/5]", 1530502617], - [279, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], - [283, 13, 10, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3244891982], - [289, 7, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [295, 7, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], - [295, 7, 250, "RSpec/ExampleLength: Example has too many lines. [6/5]", 245631994], - [304, 7, 14, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 2630471583], - [310, 7, 17, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 514323045], - [310, 7, 397, "RSpec/ExampleLength: Example has too many lines. [12/5]", 2442971902], - [325, 7, 42, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3776510226], - [325, 7, 288, "RSpec/ExampleLength: Example has too many lines. [6/5]", 2257300066], - [335, 13, 35, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2433405780], - [341, 7, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [347, 7, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], - [354, 7, 14, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 2630471583], - [360, 7, 46, "RSpec/MultipleExpectations: Example has too many expectations [5/1].", 1591700420], - [360, 7, 670, "RSpec/ExampleLength: Example has too many lines. [20/5]", 2334100751], - [383, 7, 46, "RSpec/MultipleExpectations: Example has too many expectations [5/1].", 1177358143], - [383, 7, 670, "RSpec/ExampleLength: Example has too many lines. [20/5]", 1638929140], - [406, 7, 55, "RSpec/MultipleExpectations: Example has too many expectations [5/1].", 3522215174], - [406, 7, 736, "RSpec/ExampleLength: Example has too many lines. [20/5]", 3284399531], - [429, 7, 42, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3776510226], - [429, 7, 288, "RSpec/ExampleLength: Example has too many lines. [6/5]", 2257300066], - [439, 13, 28, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 964539113], - [456, 7, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [462, 7, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], - [474, 7, 57, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3903999862], - [479, 7, 30, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3853297158], - [479, 7, 279, "RSpec/ExampleLength: Example has too many lines. [8/5]", 4123717342], - [497, 7, 38, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 55284112], - [497, 7, 501, "RSpec/ExampleLength: Example has too many lines. [12/5]", 4230649177], - [513, 7, 42, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3776510226], - [513, 7, 288, "RSpec/ExampleLength: Example has too many lines. [6/5]", 2257300066], - [553, 7, 44, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 1308784480], - [562, 7, 57, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3903999862], - [570, 13, 50, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3488997509], - [587, 7, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [601, 7, 57, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3903999862], - [606, 7, 30, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3853297158], - [606, 7, 283, "RSpec/ExampleLength: Example has too many lines. [8/5]", 2727896319], - [617, 7, 170, "RSpec/RepeatedExample: Don't repeat examples within an example group.", 982775935], - [624, 7, 234, "RSpec/RepeatedExample: Don't repeat examples within an example group.", 4222897050], - [632, 7, 42, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3776510226], - [632, 7, 287, "RSpec/ExampleLength: Example has too many lines. [6/5]", 1868238702], - [653, 7, 19, "RSpec/MultipleExpectations: Example has too many expectations [8/1].", 3032080240], - [653, 7, 608, "RSpec/ExampleLength: Example has too many lines. [11/5]", 4021278322], - [667, 7, 22, "RSpec/MultipleExpectations: Example has too many expectations [8/1].", 3267814569], - [667, 7, 802, "RSpec/ExampleLength: Example has too many lines. [16/5]", 3873702471], - [686, 7, 60, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2965285760], - [687, 9, 22, "RSpec/MultipleExpectations: Example has too many expectations [8/1].", 3267814569], - [687, 9, 840, "RSpec/ExampleLength: Example has too many lines. [16/5]", 1898577487], - [709, 7, 17, "RSpec/MultipleExpectations: Example has too many expectations [14/1].", 2729217909], - [709, 7, 1511, "RSpec/ExampleLength: Example has too many lines. [37/5]", 273151377], - [751, 7, 14, "RSpec/MultipleExpectations: Example has too many expectations [9/1].", 3862108402], - [751, 7, 878, "RSpec/ExampleLength: Example has too many lines. [17/5]", 1532494883], - [771, 7, 59, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2662855125], - [772, 9, 14, "RSpec/MultipleExpectations: Example has too many expectations [9/1].", 3862108402], - [772, 9, 953, "RSpec/ExampleLength: Example has too many lines. [18/5]", 3843570887], - [795, 13, 16, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1978044688], - [796, 7, 14, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 3059896108], - [796, 15, 6, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3149302003], - [804, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [810, 9, 14, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 2630471583], - [816, 9, 17, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 514323045], - [816, 9, 423, "RSpec/ExampleLength: Example has too many lines. [12/5]", 865951230], - [832, 7, 15, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2727260359], - [832, 15, 7, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 312814392], - [840, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [846, 9, 49, "RSpec/MultipleExpectations: Example has too many expectations [6/1].", 2703328868], - [846, 9, 644, "RSpec/ExampleLength: Example has too many lines. [15/5]", 2306651973], - [865, 7, 13, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2695947121], - [865, 15, 5, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 95220878], - [866, 9, 33, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 3220495026], - [866, 17, 25, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 992293837], - [874, 11, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [880, 11, 14, "RSpec/MultipleExpectations: Example has too many expectations [6/1].", 2630471583], - [880, 11, 661, "RSpec/ExampleLength: Example has too many lines. [15/5]", 151639928], - [899, 9, 34, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 3483761479], - [899, 17, 26, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2491245272], - [907, 11, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [913, 11, 49, "RSpec/MultipleExpectations: Example has too many expectations [6/1].", 2703328868], - [913, 11, 676, "RSpec/ExampleLength: Example has too many lines. [15/5]", 1883432005], - [935, 11, 16, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3540094847], - [936, 13, 46, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3417301734], - [937, 7, 14, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 3059896108], - [937, 15, 6, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3149302003], - [952, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [958, 9, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], - [958, 9, 264, "RSpec/ExampleLength: Example has too many lines. [6/5]", 505403802], - [968, 7, 15, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2727260359], - [968, 15, 7, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 312814392], - [977, 9, 33, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 1561266956], - [984, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [990, 9, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], - [990, 9, 264, "RSpec/ExampleLength: Example has too many lines. [6/5]", 505403802], - [1001, 13, 40, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3350133791], - [1002, 7, 14, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 3059896108], - [1002, 15, 6, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3149302003], - [1007, 9, 32, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 2446127739], - [1007, 17, 24, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1251280420], - [1018, 11, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [1024, 11, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], - [1024, 11, 278, "RSpec/ExampleLength: Example has too many lines. [6/5]", 3137650586], - [1034, 9, 36, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 2654417422], - [1034, 17, 28, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3158470033], - [1045, 11, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [1051, 11, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], - [1051, 11, 278, "RSpec/ExampleLength: Example has too many lines. [6/5]", 3137650586], - [1062, 7, 15, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2727260359], - [1062, 15, 7, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 312814392], - [1074, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [1080, 9, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], - [1080, 9, 264, "RSpec/ExampleLength: Example has too many lines. [6/5]", 505403802], - [1091, 13, 42, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2088625065], - [1092, 7, 14, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 3059896108], - [1092, 15, 6, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3149302003], - [1112, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [1118, 9, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], - [1118, 9, 264, "RSpec/ExampleLength: Example has too many lines. [6/5]", 505403802], - [1128, 7, 15, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2727260359], - [1128, 15, 7, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 312814392], - [1142, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [1148, 9, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], - [1148, 9, 264, "RSpec/ExampleLength: Example has too many lines. [6/5]", 505403802], - [1159, 13, 9, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2402616528], - [1160, 7, 17, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 1968335926], - [1160, 15, 9, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1548243657], - [1172, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [1178, 9, 23, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 564765716], - [1183, 9, 41, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3449400223], - [1188, 9, 24, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 1252366319], - [1201, 11, 25, "RSpec/MultipleExpectations: Example has too many expectations [9/1].", 2034890136], - [1201, 11, 1172, "RSpec/ExampleLength: Example has too many lines. [15/5]", 4279405416], - [1224, 9, 23, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 3239195755], - [1238, 11, 25, "RSpec/MultipleExpectations: Example has too many expectations [9/1].", 2034890136], - [1238, 11, 1090, "RSpec/ExampleLength: Example has too many lines. [15/5]", 3287951749], - [1261, 7, 18, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2670365], - [1261, 15, 10, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 80617602], - [1273, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [1279, 9, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], - [1284, 9, 49, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 2703328868], - [1291, 13, 12, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1788285844], - [1295, 7, 29, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2484467444], - [1295, 15, 21, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2487855435], - [1296, 9, 18, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 2756695113], - [1296, 17, 10, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1621560150], - [1302, 11, 44, "RSpec/MultipleExpectations: Example has too many expectations [4/1].", 1308784480], - [1303, 63, 2, "RSpec/BeEq: Prefer `be` over `eq`.", 5860785], - [1309, 11, 50, "RSpec/MultipleExpectations: Example has too many expectations [4/1].", 630326736], - [1310, 63, 2, "RSpec/BeEq: Prefer `be` over `eq`.", 5860785], - [1317, 9, 22, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 4030819019], - [1317, 17, 14, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 4209408980], - [1325, 11, 44, "RSpec/MultipleExpectations: Example has too many expectations [4/1].", 1308784480], - [1326, 63, 2, "RSpec/BeEq: Prefer `be` over `eq`.", 5860785], - [1332, 11, 54, "RSpec/MultipleExpectations: Example has too many expectations [4/1].", 1338695762], - [1333, 63, 2, "RSpec/BeEq: Prefer `be` over `eq`.", 5860785], - [1341, 7, 31, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 3799412900], - [1341, 15, 23, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 512643995], - [1350, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], - [1354, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], - [1354, 52, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], - [1357, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], - [1368, 7, 25, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 1049421877], - [1368, 15, 17, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1293766410], - [1378, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480] + [118, 15, 19, "RSpec/VariableName: Use snake_case for variable names.", 372347066], + [127, 15, 19, "RSpec/VariableName: Use snake_case for variable names.", 372347066], + [145, 15, 19, "RSpec/VariableName: Use snake_case for variable names.", 372347066], + [157, 15, 19, "RSpec/VariableName: Use snake_case for variable names.", 372347066], + [169, 15, 19, "RSpec/VariableName: Use snake_case for variable names.", 372347066], + [181, 15, 19, "RSpec/VariableName: Use snake_case for variable names.", 372347066], + [206, 11, 16, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 4266815955], + [209, 16, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], + [213, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], + [217, 16, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], + [217, 40, 2, "RSpec/BeEq: Prefer `be` over `eq`.", 5860785], + [223, 16, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], + [227, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], + [231, 16, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], + [231, 45, 2, "RSpec/BeEq: Prefer `be` over `eq`.", 5860785], + [237, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], + [243, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], + [247, 13, 12, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 491923605], + [253, 7, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [259, 7, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], + [268, 7, 19, "RSpec/MultipleExpectations: Example has too many expectations [9/1].", 2796689240], + [283, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], + [287, 13, 10, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3244891982], + [293, 7, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [299, 7, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], + [308, 7, 14, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 2630471583], + [314, 7, 17, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 514323045], + [329, 7, 42, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3776510226], + [339, 13, 35, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2433405780], + [345, 7, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [351, 7, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], + [358, 7, 14, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 2630471583], + [364, 7, 46, "RSpec/MultipleExpectations: Example has too many expectations [5/1].", 1591700420], + [387, 7, 46, "RSpec/MultipleExpectations: Example has too many expectations [5/1].", 1177358143], + [410, 7, 55, "RSpec/MultipleExpectations: Example has too many expectations [5/1].", 3522215174], + [433, 7, 42, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3776510226], + [443, 13, 28, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 964539113], + [460, 7, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [466, 7, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], + [478, 7, 57, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3903999862], + [483, 7, 30, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3853297158], + [501, 7, 38, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 55284112], + [517, 7, 42, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3776510226], + [557, 7, 44, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 1308784480], + [566, 7, 57, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3903999862], + [574, 13, 50, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3488997509], + [591, 7, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [605, 7, 57, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3903999862], + [610, 7, 30, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3853297158], + [621, 7, 170, "RSpec/RepeatedExample: Don't repeat examples within an example group.", 982775935], + [628, 7, 234, "RSpec/RepeatedExample: Don't repeat examples within an example group.", 4222897050], + [636, 7, 42, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3776510226], + [657, 7, 19, "RSpec/MultipleExpectations: Example has too many expectations [8/1].", 3032080240], + [671, 7, 22, "RSpec/MultipleExpectations: Example has too many expectations [8/1].", 3267814569], + [690, 7, 60, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2965285760], + [691, 9, 22, "RSpec/MultipleExpectations: Example has too many expectations [8/1].", 3267814569], + [713, 7, 17, "RSpec/MultipleExpectations: Example has too many expectations [15/1].", 2729217909], + [773, 7, 14, "RSpec/MultipleExpectations: Example has too many expectations [9/1].", 3862108402], + [788, 7, 59, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2662855125], + [789, 9, 14, "RSpec/MultipleExpectations: Example has too many expectations [9/1].", 3862108402], + [812, 13, 16, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1978044688], + [813, 7, 14, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 3059896108], + [813, 15, 6, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3149302003], + [821, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [827, 9, 14, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 2630471583], + [833, 9, 17, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 514323045], + [849, 7, 15, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2727260359], + [849, 15, 7, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 312814392], + [857, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [863, 9, 49, "RSpec/MultipleExpectations: Example has too many expectations [6/1].", 2703328868], + [882, 7, 13, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2695947121], + [882, 15, 5, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 95220878], + [883, 9, 33, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 3220495026], + [883, 17, 25, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 992293837], + [891, 11, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [897, 11, 14, "RSpec/MultipleExpectations: Example has too many expectations [6/1].", 2630471583], + [916, 9, 34, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 3483761479], + [916, 17, 26, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2491245272], + [924, 11, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [930, 11, 49, "RSpec/MultipleExpectations: Example has too many expectations [6/1].", 2703328868], + [952, 11, 16, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3540094847], + [953, 13, 46, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3417301734], + [954, 7, 14, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 3059896108], + [954, 15, 6, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3149302003], + [969, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [975, 9, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], + [985, 7, 15, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2727260359], + [985, 15, 7, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 312814392], + [994, 9, 33, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 1561266956], + [1001, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [1007, 9, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], + [1018, 13, 40, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3350133791], + [1019, 7, 14, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 3059896108], + [1019, 15, 6, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3149302003], + [1024, 9, 32, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 2446127739], + [1024, 17, 24, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1251280420], + [1035, 11, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [1041, 11, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], + [1051, 9, 36, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 2654417422], + [1051, 17, 28, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3158470033], + [1062, 11, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [1068, 11, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], + [1079, 7, 15, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2727260359], + [1079, 15, 7, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 312814392], + [1091, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [1097, 9, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], + [1108, 13, 42, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2088625065], + [1109, 7, 14, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 3059896108], + [1109, 15, 6, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3149302003], + [1129, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [1135, 9, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], + [1145, 7, 15, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2727260359], + [1145, 15, 7, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 312814392], + [1159, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [1165, 9, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], + [1176, 13, 9, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2402616528], + [1177, 7, 17, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 1968335926], + [1177, 15, 9, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1548243657], + [1189, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [1195, 9, 23, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 564765716], + [1200, 9, 41, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3449400223], + [1205, 9, 24, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 1252366319], + [1218, 11, 25, "RSpec/MultipleExpectations: Example has too many expectations [9/1].", 2034890136], + [1241, 9, 23, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 3239195755], + [1255, 11, 25, "RSpec/MultipleExpectations: Example has too many expectations [9/1].", 2034890136], + [1278, 7, 18, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2670365], + [1278, 15, 10, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 80617602], + [1290, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [1296, 9, 31, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 3964658991], + [1301, 9, 49, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 2703328868], + [1308, 13, 12, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1788285844], + [1312, 7, 29, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 2484467444], + [1312, 15, 21, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2487855435], + [1313, 9, 18, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 2756695113], + [1313, 17, 10, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1621560150], + [1319, 11, 44, "RSpec/MultipleExpectations: Example has too many expectations [4/1].", 1308784480], + [1320, 63, 2, "RSpec/BeEq: Prefer `be` over `eq`.", 5860785], + [1326, 11, 50, "RSpec/MultipleExpectations: Example has too many expectations [4/1].", 630326736], + [1327, 63, 2, "RSpec/BeEq: Prefer `be` over `eq`.", 5860785], + [1334, 9, 22, "RSpec/NestedGroups: Maximum example group nesting exceeded [5/3].", 4030819019], + [1334, 17, 14, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 4209408980], + [1342, 11, 44, "RSpec/MultipleExpectations: Example has too many expectations [4/1].", 1308784480], + [1343, 63, 2, "RSpec/BeEq: Prefer `be` over `eq`.", 5860785], + [1349, 11, 54, "RSpec/MultipleExpectations: Example has too many expectations [4/1].", 1338695762], + [1350, 63, 2, "RSpec/BeEq: Prefer `be` over `eq`.", 5860785], + [1358, 7, 31, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 3799412900], + [1358, 15, 23, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 512643995], + [1367, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], + [1371, 18, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], + [1371, 52, 13, "RSpec/DescribedClass: Use `described_class` instead of `SanitizeEmail`.", 3134934046], + [1374, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480], + [1385, 7, 25, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 1049421877], + [1385, 15, 17, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1293766410], + [1395, 9, 44, "RSpec/MultipleExpectations: Example has too many expectations [3/1].", 1308784480] ] } diff --git a/Appraisals b/Appraisals index 4c87d81..98d153e 100644 --- a/Appraisals +++ b/Appraisals @@ -1,29 +1,187 @@ # frozen_string_literal: true +appraise "rails-3-0" do + gem "rails", "~> 3.0.0" + gem "reek", "~> 2.0" # for Ruby < 2.0 + gem "tins", "~> 1.6.0" # for Ruby < 2.0 + gem "json", "~> 1.8.3" + gem "rake", "~> 10.0" + gem "rest-client", "~> 1.8.0" + gem "tzinfo", "~> 0.3.23" +end +appraise "rails-3-1" do + gem "actionmailer", "~> 3.1.0" + gem "railties", "~> 3.1.0" + gem "reek", "~> 2.0" # for Ruby < 2.0 + gem "tins", "~> 1.6.0" # for Ruby < 2.0 + gem "json", "~> 1.8.3" + gem "rake", "~> 10.0" + gem "rest-client", "~> 1.8.0" + gem "tzinfo", "~> 1.0" +end +appraise "rails-3-2" do + gem "actionmailer", "~> 3.2.0" + gem "railties", "~> 3.2.0" + # reek >= 4.0 requires Ruby 2.1 minimum + gem "reek", "~>3.11.0" + gem "json", "~> 1.8.3" + gem "rake", "~> 10.0" + gem "tzinfo", "~> 1.0" +end + +# Compat: Ruby >= 1.9.3 +# Test Matrix: +# - Ruby 2.3 +appraise "rails-4-0" do + # Load order is very important with combustion! + gem "combustion", "~> 1.4" + + gem "actionmailer", "~> 4.0.13" + gem "railties", "~> 4.0.13" + # gem "actionpack", "~> 4.0.13" + gem "rdoc", "6.1.2.1" + gem "json", ">= 1.7.7", "~> 1.7" + # gem "rspec-rails", "~> 3.0" # For Rails 4 +end + +# Compat: Ruby >= 1.9.3 +# Test Matrix: +# - Ruby 2.3 +appraise "rails-4-1" do + # Load order is very important with combustion! + gem "combustion", "~> 1.4" + + gem "actionmailer", "~> 4.1.16" + gem "railties", "~> 4.1.16" + # gem "actionpack", "~> 4.1.16" + gem "rdoc", "6.1.2.1" + gem "json", ">= 1.7.7", "~> 1.7" + # gem "rspec-rails", "~> 3.0" # For Rails 4 +end + +# Compat: Ruby >= 1.9.3 +# Test Matrix: +# - Ruby 2.3 +# - Ruby 2.4 appraise "rails-4-2" do - gem "actionmailer", "~> 4.2.0" - gem "railties", "~> 4.2.0" - gem "json", "~> 2.0" - gem "rake", "~> 11.0" + # Load order is very important with combustion! + gem "combustion", "~> 1.4" + + gem "actionmailer", "~> 4.2.11.3" + gem "railties", "~> 4.2.11.3" + # gem "actionpack", "~> 4.2.11.3" + gem "rdoc", "6.1.2.1" + gem "nokogiri" + # gem "rspec-rails", "~> 3.0" # For Rails 4 end +# Compat: Ruby >= 2.2.2 +# Test Matrix: +# - Ruby 2.3 +# - Ruby 2.4 appraise "rails-5-0" do - gem "actionmailer", "~> 5.0.0" - gem "railties", "~> 5.0.0" - gem "json", "~> 2.0" - gem "rake", "~> 12.0" + # Load order is very important with combustion! + gem "combustion", "~> 1.4" + + gem "actionmailer", "~> 5.0.7.2" + gem "railties", "~> 5.0.7.2" + # gem "actionpack", "~> 5.0.7.2" + gem "nokogiri" + # gem "rspec-rails", "~> 4.0" # For Rails 5.0 & 5.1 end +# Compat: Ruby >= 2.2.2 +# Test Matrix: +# - Ruby 2.3 +# - Ruby 2.4 +# - Ruby 2.5 appraise "rails-5-1" do - gem "actionmailer", "~> 5.1.0" - gem "railties", "~> 5.1.0" - gem "json", "~> 2.0" - gem "rake", "~> 12.0" + # Load order is very important with combustion! + gem "combustion", "~> 1.4" + + gem "actionmailer", "~> 5.1.7" + gem "railties", "~> 5.1.7" + # gem "actionpack", "~> 5.1.7" + gem "nokogiri" + # gem "rspec-rails", "~> 4.0" # For Rails 5.0 & 5.1 end +# Compat: Ruby >= 2.2.2 +# Test Matrix: +# - Ruby 2.3 +# - Ruby 2.4 +# - Ruby 2.5 +# - Ruby 2.6 +# - Ruby 2.7 appraise "rails-5-2" do - gem "actionmailer", "~> 5.2.0" - gem "railties", "~> 5.2.0" - gem "json", "~> 2.0" - gem "rake", "~> 12.0" + # Load order is very important with combustion! + gem "combustion", "~> 1.4" + + gem "actionmailer", "~> 5.2.8.1" + gem "railties", "~> 5.2.8.1" + # gem "actionpack", "~> 5.2.8.1" + gem "nokogiri" + # gem "rspec-rails", "~> 5.0" # For Rails 5.2 & Rails 6.0 +end + +# Compat: Ruby >= 2.5 +# Test Matrix: +# - Ruby 2.5 +# - Ruby 2.6 +# - Ruby 2.7 +appraise "rails-6-0" do + # Load order is very important with combustion! + gem "combustion", "~> 1.4" + + gem "actionmailer", "~> 6.0.6.1" + gem "railties", "~> 6.0.6.1" + # gem "actionpack", "~> 6.0.6.1" + # gem "rspec-rails", "~> 5.0" # For Rails 5.2 & Rails 6.0 +end + +# Compat: Ruby >= 2.5 +# Test Matrix: +# - Ruby 2.5 +# - Ruby 2.6 +# - Ruby 2.7 +# - Ruby 3.0 +appraise "rails-6-1" do + # Load order is very important with combustion! + gem "combustion", "~> 1.4" + + gem "actionmailer", "~> 6.1.7.7" + gem "railties", "~> 6.1.7.7" + # gem "actionpack", "~> 6.1.7.7" + # gem "rspec-rails", "~> 6.0" # For Rails 6.1 & Rails 7.0 - 7.1 +end + +# Compat: Ruby >= 2.7 +# Test Matrix: +# - Ruby 2.7 +# - Ruby 3.0 +# - Ruby 3.1 +appraise "rails-7-0" do + # Load order is very important with combustion! + gem "combustion", "~> 1.4" + + gem "actionmailer", "~> 7.0.8.1" + gem "railties", "~> 7.0.8.1" + # gem "actionpack", "~> 7.0.8.1" + # gem "rspec-rails", "~> 6.0" # For Rails 6.1 & Rails 7.0 - 7.1 +end + +# Compat: Ruby >= 2.7 +# Test Matrix: +# - Ruby 2.7 +# - Ruby 3.0 +# - Ruby 3.1 +# - Ruby 3.2 +appraise "rails-7-1" do + # Load order is very important with combustion! + gem "combustion", "~> 1.4" + + gem "actionmailer", "~> 7.1.3.2" + gem "railties", "~> 7.1.3.2" + # gem "actionpack", "~> 7.1.3.2" + # gem "rspec-rails", "~> 6.0" # For Rails 6.1 & Rails 7.0 - 7.1 end diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f3b0b4..7a65328 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed ### Removed +## [2.0.6] - 2024-04-25 ([tag][2.0.6t]) +### Added +* Appraisals & Combustion for comprehensive testing across versions of Rails (@pboling) +* Rails 3.0 to Test Matrix (@pboling) +* Rails 3.1 to Test Matrix (@pboling) +* Rails 3.2 to Test Matrix (@pboling) +* Rails 4.0 to Test Matrix (@pboling) +* Rails 4.1 to Test Matrix (@pboling) +* Rails 4.2 to Test Matrix (@pboling) +* Rails 5.0 to Test Matrix (@pboling) +* Rails 5.1 to Test Matrix (@pboling) +* More Documentation (@pboling) +### Fixed +* Compatibility with Rails 3.0, 3.1, 3.2 (@pboling) +* Compatibility with Rails 6.0, 6.1, 7.0, 7.1 (@pboling) + ## [2.0.5] - 2024-04-18 ([tag][2.0.5t]) ### Added * New RSpec matcher (@pboling) @@ -275,7 +291,9 @@ Old version? * Fixed require paths * added about.yml and this CHANGELOG -[Unreleased]: https://github.com/pboling/sanitize_email/compare/v2.0.5...HEAD +[Unreleased]: https://github.com/pboling/sanitize_email/compare/v2.0.6...HEAD +[2.0.6]: https://github.com/pboling/sanitize_email/compare/v2.0.5...v2.0.6 +[2.0.6t]: https://github.com/pboling/sanitize_email/tags/v2.0.6 [2.0.5]: https://github.com/pboling/sanitize_email/compare/v2.0.4...v2.0.5 [2.0.5t]: https://github.com/pboling/sanitize_email/tags/v2.0.5 [2.0.4]: https://github.com/pboling/sanitize_email/compare/v2.0.3...v2.0.4 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e2d7b81..e1eee1a 100755 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,6 +7,14 @@ the [code of conduct][🀝conduct]. To submit a patch, please fork the project and create a patch with tests. Once you're happy with it send a pull request and post a message to the [gitter chat][🏘chat]. +## Appraisal & Combustion + +### Generate a new set of Appraisal gemfiles: + +```sh +BUNDLE_GEMFILE=gemfiles/vanilla.gemfile appraisal generate +``` + ## Release To release a new version: diff --git a/Gemfile b/Gemfile index 1e7c8c2..6259dbc 100644 --- a/Gemfile +++ b/Gemfile @@ -4,6 +4,8 @@ source "https://rubygems.org" git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } +gem "combustion", "~> 1.4" + # Specify your gem's dependencies in sanitize_email.gemspec gemspec @@ -12,6 +14,10 @@ platform :mri do gem "byebug", ">= 11" end +gem "actionmailer", "~> 7.1.3.2" +gem "railties", "~> 7.1.3.2" +# gem "actionpack", "~> 7.1.3.2" + # Coverage gem "kettle-soup-cover", "~> 1.0", ">= 1.0.2" diff --git a/Gemfile.lock b/Gemfile.lock index 555e7b2..96b3021 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,29 +1,13 @@ PATH remote: . specs: - sanitize_email (2.0.5) + sanitize_email (2.0.6) mail (~> 2.0) version_gem (~> 1.1, >= 1.1.4) GEM remote: https://rubygems.org/ specs: - actioncable (7.1.3.2) - actionpack (= 7.1.3.2) - activesupport (= 7.1.3.2) - nio4r (~> 2.0) - websocket-driver (>= 0.6.1) - zeitwerk (~> 2.6) - actionmailbox (7.1.3.2) - actionpack (= 7.1.3.2) - activejob (= 7.1.3.2) - activerecord (= 7.1.3.2) - activestorage (= 7.1.3.2) - activesupport (= 7.1.3.2) - mail (>= 2.7.1) - net-imap - net-pop - net-smtp actionmailer (7.1.3.2) actionpack (= 7.1.3.2) actionview (= 7.1.3.2) @@ -44,13 +28,6 @@ GEM rack-test (>= 0.6.3) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - actiontext (7.1.3.2) - actionpack (= 7.1.3.2) - activerecord (= 7.1.3.2) - activestorage (= 7.1.3.2) - activesupport (= 7.1.3.2) - globalid (>= 0.6.0) - nokogiri (>= 1.8.5) actionview (7.1.3.2) activesupport (= 7.1.3.2) builder (~> 3.1) @@ -60,18 +37,6 @@ GEM activejob (7.1.3.2) activesupport (= 7.1.3.2) globalid (>= 0.3.6) - activemodel (7.1.3.2) - activesupport (= 7.1.3.2) - activerecord (7.1.3.2) - activemodel (= 7.1.3.2) - activesupport (= 7.1.3.2) - timeout (>= 0.4.0) - activestorage (7.1.3.2) - actionpack (= 7.1.3.2) - activejob (= 7.1.3.2) - activerecord (= 7.1.3.2) - activesupport (= 7.1.3.2) - marcel (~> 1.0) activesupport (7.1.3.2) base64 bigdecimal @@ -92,6 +57,10 @@ GEM bigdecimal (3.1.7) builder (3.2.4) byebug (11.1.3) + combustion (1.4.0) + activesupport (>= 3.0.0) + railties (>= 3.0.0) + thor (>= 0.14.6) concurrent-ruby (1.2.3) connection_pool (2.4.1) crass (1.0.6) @@ -156,8 +125,8 @@ GEM net-imap net-pop net-smtp - marcel (1.0.4) mini_mime (1.1.5) + mini_portile2 (2.8.6) minitest (5.22.3) mutex_m (0.2.0) net-imap (0.4.10) @@ -169,19 +138,11 @@ GEM timeout net-smtp (0.5.0) net-protocol - nio4r (2.7.1) - nokogiri (1.16.4-aarch64-linux) - racc (~> 1.4) - nokogiri (1.16.4-arm-linux) + nokogiri (1.16.4) + mini_portile2 (~> 2.8.2) racc (~> 1.4) nokogiri (1.16.4-arm64-darwin) racc (~> 1.4) - nokogiri (1.16.4-x86-linux) - racc (~> 1.4) - nokogiri (1.16.4-x86_64-darwin) - racc (~> 1.4) - nokogiri (1.16.4-x86_64-linux) - racc (~> 1.4) parallel (1.24.0) parser (3.3.0.5) ast (~> 2.4.1) @@ -197,20 +158,6 @@ GEM rackup (2.1.0) rack (>= 3) webrick (~> 1.8) - rails (7.1.3.2) - actioncable (= 7.1.3.2) - actionmailbox (= 7.1.3.2) - actionmailer (= 7.1.3.2) - actionpack (= 7.1.3.2) - actiontext (= 7.1.3.2) - actionview (= 7.1.3.2) - activejob (= 7.1.3.2) - activemodel (= 7.1.3.2) - activerecord (= 7.1.3.2) - activestorage (= 7.1.3.2) - activesupport (= 7.1.3.2) - bundler (>= 1.15.0) - railties (= 7.1.3.2) rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest @@ -236,7 +183,7 @@ GEM rainbow (>= 2.0, < 4.0) rexml (~> 3.1) regexp_parser (2.9.0) - reline (0.5.2) + reline (0.5.3) io-console (~> 0.5) rexml (3.2.6) rspec (3.13.0) @@ -359,27 +306,22 @@ GEM unicode-display_width (2.5.0) version_gem (1.1.4) webrick (1.8.1) - websocket-driver (0.7.6) - websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.5) zeitwerk (2.6.13) PLATFORMS - aarch64-linux - arm-linux - arm64-darwin - x86-linux - x86_64-darwin - x86_64-linux + arm64-darwin-23 + ruby DEPENDENCIES - actionmailer (>= 3) - appraisal (~> 2) + actionmailer (~> 7.1.3.2) + appraisal (~> 2.5) byebug (>= 11) + combustion (~> 1.4) + json (>= 1.7.7) kettle-soup-cover (~> 1.0, >= 1.0.2) - rails (>= 3.0, <= 8) - rake (>= 12) - rdoc (>= 3.12) + railties (~> 7.1.3.2) + rake (>= 0.8.7) + rdoc (>= 3) reek (~> 6.3) rspec (>= 3) rspec-block_is_expected (~> 1.0, >= 1.0.5) diff --git a/README.md b/README.md index 87b7278..621be83 100644 --- a/README.md +++ b/README.md @@ -63,13 +63,15 @@ then this is the gem for you. ## Compatibility -βš™οΈ Compatible with all versions of Ruby >= 2.3. +βš™οΈ Compatible with all versions of Ruby >= 2.3, plus JRuby and Truffleruby. βš™οΈ Compatible with all Ruby web Frameworks (Hanami, Roda, Sinatra, Rails). βš™οΈ Compatible with all versions of Rails from 3.0 - 7.1+. βš™οΈ Compatible with scripted usage of Mail gem outside a web framework. βš™οΈ Compatible with [`sendgrid-actionmailer`](https://github.com/eddiezane/sendgrid-actionmailer)'s support for personalizations, and will override email addresses there according to the configuration. βš™οΈ If this gem is not compatible with your use case, and you'd like it to be, I'd like to hear about it! +It was a slog getting (very nearly) the entire compatibility matrix working with Github Actions, [`appraisal`](https://github.com/thoughtbot/appraisal), and [`combustion`](https://github.com/pat/combustion), and I'm very interested in hearing about ways to improve it! + ## πŸ›ž DVCS This project does not trust any one version control system, @@ -228,7 +230,7 @@ The link tokens in the following sections should be kept ordered by the row and It's particularly helpful when you want to prevent the delivery of email (e.g. in development/test environments) or alter the to/cc/bcc (e.g. in staging or demo environments) of all email generated from your application. * compatible without Rails! Can work with just the `mail` gem. -* compatible with Rails >= 4.2. See gem versions 1.x for older versions of Rails. +* compatible with Rails >= 3.0. See gem versions 1.x for older versions of Rails. * compatible with Ruby >= 2.3. See gem versions 1.x for older versions of Ruby. * compatible with any Ruby app with a mail handler that uses the `register_interceptor` API (a la ActionMailer and `mail` gems) * configure it and forget it @@ -674,15 +676,18 @@ Learn more about, or become one of, our πŸŽ– contributors on: ## Running Specs The basic compatibility matrix: -``` +```sh appraisal install appraisal rake test ``` Sometimes also: +```sh +BUNDLE_GEMFILE=gemfiles/vanilla.gemfile appraisal update ``` -appraisal update -``` + +Except, is unlikely to be possible to install all of the supported Rubies & Railsies in a single container... +See the various github action workflows for more inspiration on running certain oldies. ### Code Coverage diff --git a/config.ru b/config.ru new file mode 100644 index 0000000..3060b30 --- /dev/null +++ b/config.ru @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require "rubygems" +require "bundler" + +Bundler.require :default, :development + +Combustion.initialize!(:all) +run Combustion::Application diff --git a/gemfiles/coverage.gemfile b/gemfiles/coverage.gemfile index e8f3763..19b5aab 100644 --- a/gemfiles/coverage.gemfile +++ b/gemfiles/coverage.gemfile @@ -2,6 +2,14 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } source "https://rubygems.org" +# Load order is very important with combustion! +gem "combustion", "~> 1.4" + +gem "actionmailer", "~> 7.1.3.2" +gem "railties", "~> 7.1.3.2" +gem "actionpack", "~> 7.1.3.2" +# gem "rspec-rails", "~> 6.0" # For Rails 6.1 & Rails 7.0 - 7.1 + # Root Gemfile is only for local development only. It is not loaded on CI. # On CI we only need the gemspecs' dependencies (including development dependencies). # Exceptions, if any, will be found in gemfiles/*.gemfile diff --git a/gemfiles/rails_3_0.gemfile b/gemfiles/rails_3_0.gemfile new file mode 100644 index 0000000..ef0fc72 --- /dev/null +++ b/gemfiles/rails_3_0.gemfile @@ -0,0 +1,16 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "combustion", "~> 1.4" +gem "actionmailer" +gem "railties" +gem "rails", "~> 3.0.0" +gem "reek", "~> 2.0" +gem "tins", "~> 1.6.0" +gem "json", "~> 1.8.3" +gem "rake", "~> 10.0" +gem "rest-client", "~> 1.8.0" +gem "tzinfo", "~> 0.3.23" + +gemspec path: "../" diff --git a/gemfiles/rails_3_1.gemfile b/gemfiles/rails_3_1.gemfile new file mode 100644 index 0000000..1d63e22 --- /dev/null +++ b/gemfiles/rails_3_1.gemfile @@ -0,0 +1,15 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "combustion", "~> 1.4" +gem "actionmailer", "~> 3.1.0" +gem "railties", "~> 3.1.0" +gem "reek", "~> 2.0" +gem "tins", "~> 1.6.0" +gem "json", "~> 1.8.3" +gem "rake", "~> 10.0" +gem "rest-client", "~> 1.8.0" +gem "tzinfo", "~> 1.0" + +gemspec path: "../" diff --git a/gemfiles/rails_3_2.gemfile b/gemfiles/rails_3_2.gemfile new file mode 100644 index 0000000..ec25657 --- /dev/null +++ b/gemfiles/rails_3_2.gemfile @@ -0,0 +1,13 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "combustion", "~> 1.4" +gem "actionmailer", "~> 3.2.0" +gem "railties", "~> 3.2.0" +gem "reek", "~>3.11.0" +gem "json", "~> 1.8.3" +gem "rake", "~> 10.0" +gem "tzinfo", "~> 1.0" + +gemspec path: "../" diff --git a/gemfiles/rails_4_0.gemfile b/gemfiles/rails_4_0.gemfile new file mode 100644 index 0000000..0365167 --- /dev/null +++ b/gemfiles/rails_4_0.gemfile @@ -0,0 +1,11 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "combustion", "~> 1.4" +gem "actionmailer", "~> 4.0.13" +gem "railties", "~> 4.0.13" +gem "rdoc", "6.1.2.1" +gem "json", ">= 1.7.7", "~> 1.7" + +gemspec path: "../" diff --git a/gemfiles/rails_4_1.gemfile b/gemfiles/rails_4_1.gemfile new file mode 100644 index 0000000..2f789f7 --- /dev/null +++ b/gemfiles/rails_4_1.gemfile @@ -0,0 +1,11 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "combustion", "~> 1.4" +gem "actionmailer", "~> 4.1.16" +gem "railties", "~> 4.1.16" +gem "rdoc", "6.1.2.1" +gem "json", ">= 1.7.7", "~> 1.7" + +gemspec path: "../" diff --git a/gemfiles/rails_4_2.gemfile b/gemfiles/rails_4_2.gemfile index 4b4b64a..2cdc0c4 100644 --- a/gemfiles/rails_4_2.gemfile +++ b/gemfiles/rails_4_2.gemfile @@ -2,16 +2,10 @@ source "https://rubygems.org" -gem "actionmailer", "~> 4.2.0" -gem "railties", "~> 4.2.0" -gem "json", "~> 2.0" -gem "rake", "~> 11.0" - -group :test do - # Travis-CI does not support C-extensions on JRuby - gem "rubocop", "~> 0.58.0", platforms: :mri - gem "rubocop-rspec", "~> 1.29.0", platforms: :mri - gem "byebug", platforms: :mri -end +gem "combustion", "~> 1.4" +gem "actionmailer", "~> 4.2.11.3" +gem "railties", "~> 4.2.11.3" +gem "rdoc", "6.1.2.1" +gem "nokogiri" gemspec path: "../" diff --git a/gemfiles/rails_5_0.gemfile b/gemfiles/rails_5_0.gemfile index a42023e..27990ed 100644 --- a/gemfiles/rails_5_0.gemfile +++ b/gemfiles/rails_5_0.gemfile @@ -2,16 +2,9 @@ source "https://rubygems.org" -gem "actionmailer", "~> 5.0.0" -gem "railties", "~> 5.0.0" -gem "json", "~> 2.0" -gem "rake", "~> 12.0" - -group :test do - # Travis-CI does not support C-extensions on JRuby - gem "rubocop", "~> 0.58.0", platforms: :mri - gem "rubocop-rspec", "~> 1.29.0", platforms: :mri - gem "byebug", platforms: :mri -end +gem "combustion", "~> 1.4" +gem "actionmailer", "~> 5.0.7.2" +gem "railties", "~> 5.0.7.2" +gem "nokogiri" gemspec path: "../" diff --git a/gemfiles/rails_5_1.gemfile b/gemfiles/rails_5_1.gemfile index f6acc75..7221400 100644 --- a/gemfiles/rails_5_1.gemfile +++ b/gemfiles/rails_5_1.gemfile @@ -2,16 +2,9 @@ source "https://rubygems.org" -gem "actionmailer", "~> 5.1.0" -gem "railties", "~> 5.1.0" -gem "json", "~> 2.0" -gem "rake", "~> 12.0" - -group :test do - # Travis-CI does not support C-extensions on JRuby - gem "rubocop", "~> 0.58.0", platforms: :mri - gem "rubocop-rspec", "~> 1.29.0", platforms: :mri - gem "byebug", platforms: :mri -end +gem "combustion", "~> 1.4" +gem "actionmailer", "~> 5.1.7" +gem "railties", "~> 5.1.7" +gem "nokogiri" gemspec path: "../" diff --git a/gemfiles/rails_5_2.gemfile b/gemfiles/rails_5_2.gemfile index 2029be0..d1b6283 100644 --- a/gemfiles/rails_5_2.gemfile +++ b/gemfiles/rails_5_2.gemfile @@ -2,16 +2,9 @@ source "https://rubygems.org" -gem "actionmailer", "~> 5.2.0" -gem "railties", "~> 5.2.0" -gem "json", "~> 2.0" -gem "rake", "~> 12.0" - -group :test do - # Travis-CI does not support C-extensions on JRuby - gem "rubocop", "~> 0.58.0", platforms: :mri - gem "rubocop-rspec", "~> 1.29.0", platforms: :mri - gem "byebug", platforms: :mri -end +gem "combustion", "~> 1.4" +gem "actionmailer", "~> 5.2.8.1" +gem "railties", "~> 5.2.8.1" +gem "nokogiri" gemspec path: "../" diff --git a/gemfiles/rails_6_0.gemfile b/gemfiles/rails_6_0.gemfile new file mode 100644 index 0000000..a30a4b0 --- /dev/null +++ b/gemfiles/rails_6_0.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "combustion", "~> 1.4" +gem "actionmailer", "~> 6.0.6.1" +gem "railties", "~> 6.0.6.1" + +gemspec path: "../" diff --git a/gemfiles/rails_6_1.gemfile b/gemfiles/rails_6_1.gemfile new file mode 100644 index 0000000..77a656d --- /dev/null +++ b/gemfiles/rails_6_1.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "combustion", "~> 1.4" +gem "actionmailer", "~> 6.1.7.7" +gem "railties", "~> 6.1.7.7" + +gemspec path: "../" diff --git a/gemfiles/rails_7_0.gemfile b/gemfiles/rails_7_0.gemfile new file mode 100644 index 0000000..16bbd3c --- /dev/null +++ b/gemfiles/rails_7_0.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "combustion", "~> 1.4" +gem "actionmailer", "~> 7.0.8.1" +gem "railties", "~> 7.0.8.1" + +gemspec path: "../" diff --git a/gemfiles/rails_7_1.gemfile b/gemfiles/rails_7_1.gemfile new file mode 100644 index 0000000..080ee8b --- /dev/null +++ b/gemfiles/rails_7_1.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "combustion", "~> 1.4" +gem "actionmailer", "~> 7.1.3.2" +gem "railties", "~> 7.1.3.2" + +gemspec path: "../" diff --git a/gemfiles/style.gemfile b/gemfiles/style.gemfile index e2e46d4..acd26f5 100644 --- a/gemfiles/style.gemfile +++ b/gemfiles/style.gemfile @@ -2,6 +2,14 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } source "https://rubygems.org" +# Load order is very important with combustion! +gem "combustion", "~> 1.4" + +gem "actionmailer", "~> 7.1.3.2" +gem "railties", "~> 7.1.3.2" +gem "actionpack", "~> 7.1.3.2" +# gem "rspec-rails", "~> 6.0" # For Rails 6.1 & Rails 7.0 - 7.1 + # Root Gemfile is only for local development only. It is not loaded on CI. # On CI we only need the gemspecs' dependencies (including development dependencies). # Exceptions, if any, will be found in gemfiles/*.gemfile diff --git a/gemfiles/vanilla.gemfile b/gemfiles/vanilla.gemfile index b45c4e8..a06d69e 100644 --- a/gemfiles/vanilla.gemfile +++ b/gemfiles/vanilla.gemfile @@ -5,5 +5,10 @@ source "https://rubygems.org" # Root Gemfile is only for local development only. It is not loaded on CI. # On CI we only need the gemspecs' dependencies (including development dependencies). # Exceptions, if any, will be found in gemfiles/*.gemfile +# Load order is very important with combustion! +gem "combustion", "~> 1.4" + +gem "actionmailer" +gem "railties" gemspec path: "../" diff --git a/lib/sanitize_email.rb b/lib/sanitize_email.rb index edb894b..a951fd0 100644 --- a/lib/sanitize_email.rb +++ b/lib/sanitize_email.rb @@ -18,6 +18,9 @@ module SanitizeEmail # Error is raised when a block parameter is required and not provided to a method class MissingBlockParameter < StandardError; end + # Load order matters here! + # This gem must be loaded **after** Rails in order for the Engine/Railtie to register itself automatically. + # Otherwise, you'd have to manually require what you need from below. # Allow non-rails implementations to use this gem if defined?(::Rails) && defined?(::Rails::VERSION) if defined?(::Rails::Engine) @@ -48,95 +51,101 @@ class MissingBlockParameter < StandardError; end end end - def self.[](key) - return unless key.respond_to?(:to_sym) - SanitizeEmail::Config.config[key.to_sym] - end + class << self + extend SanitizeEmail::Deprecation - def self.method_missing(name, *_args) - SanitizeEmail[name] - end + attr_accessor :force_sanitize - # NOTE: Deprecated method - # We have to actually define because we can't deprecate methods that are hooked up via method_missing - def self.sanitized_recipients - # NOOP - This method is never actually executed, because the deprecations redirects the call to sanitized_to - end + def [](key) + return unless key.respond_to?(:to_sym) + SanitizeEmail::Config.config[key.to_sym] + end - # NOTE: Deprecated method - # We have to actually define because we can't deprecate methods that are hooked up via method_missing - def self.local_environments - SanitizeEmail::Config.config[:local_environments] - end + def method_missing(name, *_args) + if name + SanitizeEmail[name] + else + super + end + end - def self.activate?(message) - proc = SanitizeEmail::Config.config[:activation_proc] - proc.call(message) if proc.respond_to?(:call) - end + def respond_to_missing?(method_name, include_private = false) + method_name ? method_name : super + end - class << self - attr_accessor :force_sanitize - end - @force_sanitize = nil + # NOTE: Deprecated method + # We have to actually define because we can't deprecate methods that are hooked up via method_missing + def sanitized_recipients + # NOOP - This method is never actually executed, because the deprecations redirects the call to sanitized_to + end - # Regardless of the Config settings of SanitizeEmail you can do a local - # override to send sanitary email in any environment. - # You have access to all the same configuration options in the parameter hash - # as you can set in the actual SanitizeEmail.configure block. - # - # SanitizeEmail.sanitary({:sanitized_to => "boo@example.com"}) do - # Mail.deliver do - # from "from@example.org" - # # Will actually be sent to the override addresses, not this one: - # to "to@example.org" - # reply_to "reply_to@example.org" - # subject "subject" - # end - # end - # - def self.sanitary(config_options = {}) - raise MissingBlockParameter, "SanitizeEmail.sanitary must be called with a block" unless block_given? - janitor(forcing: true) do - original = SanitizeEmail::Config.config.dup - SanitizeEmail::Config.config.merge!(config_options) - yield - SanitizeEmail::Config.config = original + # NOTE: Deprecated method + # We have to actually define because we can't deprecate methods that are hooked up via method_missing + def local_environments + SanitizeEmail::Config.config[:local_environments] end - end - # Regardless of the Config settings of SanitizeEmail you can do a local - # override to force unsanitary email in any environment. - # - # SanitizeEmail.unsanitary do - # Mail.deliver do - # from "from@example.org" - # to "to@example.org" - # reply_to "reply_to@example.org" - # subject "subject" - # end - # end - # - def self.unsanitary - raise MissingBlockParameter, "SanitizeEmail.unsanitary must be called with a block" unless block_given? - janitor(forcing: false) do - yield + def activate?(message) + proc = SanitizeEmail::Config.config[:activation_proc] + proc.call(message) if proc.respond_to?(:call) end - end - def self.janitor(options) - raise MissingBlockParameter, "SanitizeEmail.janitor must be called with a block" unless block_given? - original = SanitizeEmail.force_sanitize - SanitizeEmail.force_sanitize = options[:forcing] - yield - SanitizeEmail.force_sanitize = original - end + # Regardless of the Config settings of SanitizeEmail you can do a local + # override to send sanitary email in any environment. + # You have access to all the same configuration options in the parameter hash + # as you can set in the actual SanitizeEmail.configure block. + # + # SanitizeEmail.sanitary({:sanitized_to => "boo@example.com"}) do + # Mail.deliver do + # from "from@example.org" + # # Will actually be sent to the override addresses, not this one: + # to "to@example.org" + # reply_to "reply_to@example.org" + # subject "subject" + # end + # end + # + def sanitary(config_options = {}) + raise MissingBlockParameter, "SanitizeEmail.sanitary must be called with a block" unless block_given? + janitor(forcing: true) do + original = SanitizeEmail::Config.config.dup + SanitizeEmail::Config.config.merge!(config_options) + yield + SanitizeEmail::Config.config = original + end + end + + # Regardless of the Config settings of SanitizeEmail you can do a local + # override to force unsanitary email in any environment. + # + # SanitizeEmail.unsanitary do + # Mail.deliver do + # from "from@example.org" + # to "to@example.org" + # reply_to "reply_to@example.org" + # subject "subject" + # end + # end + # + def unsanitary + raise MissingBlockParameter, "SanitizeEmail.unsanitary must be called with a block" unless block_given? + janitor(forcing: false) do + yield + end + end + + def janitor(options) + raise MissingBlockParameter, "SanitizeEmail.janitor must be called with a block" unless block_given? + original = SanitizeEmail.force_sanitize + SanitizeEmail.force_sanitize = options[:forcing] + yield + SanitizeEmail.force_sanitize = original + end - # Setup Deprecations! - class << self - extend SanitizeEmail::Deprecation deprecated_alias :sanitized_recipients, :sanitized_to deprecated :local_environments, :activation_proc end + @force_sanitize = nil end SanitizeEmail::Version.class_eval do diff --git a/lib/sanitize_email/engine_v5.rb b/lib/sanitize_email/engine_v5.rb index b9a0610..097b907 100644 --- a/lib/sanitize_email/engine_v5.rb +++ b/lib/sanitize_email/engine_v5.rb @@ -2,6 +2,7 @@ # Copyright (c) 2008 - 2018, 2020, 2022, 2024 Peter H. Boling of RailsBling.com # Released under the MIT license +require "rails/engine" module SanitizeEmail # For Rails >= 3.1, < 6.0 diff --git a/lib/sanitize_email/engine_v6.rb b/lib/sanitize_email/engine_v6.rb index adba025..61f7e4f 100644 --- a/lib/sanitize_email/engine_v6.rb +++ b/lib/sanitize_email/engine_v6.rb @@ -2,14 +2,15 @@ # Copyright (c) 2008 - 2018, 2020, 2022, 2024 Peter H. Boling of RailsBling.com # Released under the MIT license +require "rails/engine" module SanitizeEmail # For Rails >= 6.0 - class EngineV5 < ::Rails::Engine + class EngineV6 < ::Rails::Engine config.to_prepare do # For the reasoning behind the difference between v5 and v6 engines, # - see: https://github.com/rails/rails/issues/36546#issuecomment-850888284 - config.action_mailer.register_interceptor(SanitizeEmail::Bleach) + Rails.application.config.action_mailer.register_interceptor(SanitizeEmail::Bleach) end end end diff --git a/lib/sanitize_email/mail_ext.rb b/lib/sanitize_email/mail_ext.rb index 35b5baa..e9e0496 100644 --- a/lib/sanitize_email/mail_ext.rb +++ b/lib/sanitize_email/mail_ext.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +# Copyright (c) 2008 - 2018, 2020, 2022, 2024 Peter H. Boling of RailsBling.com +# Released under the MIT license require "mail" # Cribbed from email_spec gem diff --git a/lib/sanitize_email/overridden_addresses.rb b/lib/sanitize_email/overridden_addresses.rb index 4bfc824..2489606 100644 --- a/lib/sanitize_email/overridden_addresses.rb +++ b/lib/sanitize_email/overridden_addresses.rb @@ -55,10 +55,15 @@ def initialize(message, **args) @overridden_cc = tempmail[:cc].decoded @overridden_bcc = tempmail[:bcc].decoded - if message["personalizations"].nil? + actual_personalizations = message["personalizations"] + if actual_personalizations.nil? raise MissingRecipients, "No recipients left post-sanitization" if (tempmail.to + tempmail.cc + tempmail.bcc).empty? + elsif actual_personalizations.respond_to?(:unparsed_value) + @overridden_personalizations = personalizations_override(actual_personalizations) else - @overridden_personalizations = personalizations_override(message["personalizations"]) + # TODO: Remove check when dropping Rails 3.x + # undefined method `unparsed_value' for # + raise MissingRecipients, "Mail version is too old to use personalizations" end end diff --git a/lib/sanitize_email/railtie.rb b/lib/sanitize_email/railtie.rb index 279d402..d567172 100644 --- a/lib/sanitize_email/railtie.rb +++ b/lib/sanitize_email/railtie.rb @@ -2,6 +2,7 @@ # Copyright (c) 2008 - 2018, 2020, 2022, 2024 Peter H. Boling of RailsBling.com # Released under the MIT license +require "rails/railtie" module SanitizeEmail # For Rails 3.0, which didn't yet support Engines diff --git a/lib/sanitize_email/version.rb b/lib/sanitize_email/version.rb index 154587c..4ff2027 100644 --- a/lib/sanitize_email/version.rb +++ b/lib/sanitize_email/version.rb @@ -5,6 +5,6 @@ module SanitizeEmail module Version - VERSION = "2.0.5" + VERSION = "2.0.6" end end diff --git a/sanitize_email.gemspec b/sanitize_email.gemspec index 22742a0..5073840 100644 --- a/sanitize_email.gemspec +++ b/sanitize_email.gemspec @@ -56,11 +56,10 @@ Gem::Specification.new do |spec| spec.add_dependency("version_gem", "~> 1.1", ">= 1.1.4") # Development Dependencies - spec.add_development_dependency("actionmailer", ">= 3") - spec.add_development_dependency("appraisal", "~> 2") - spec.add_development_dependency("rails", ">= 3.0", "<= 8") - spec.add_development_dependency("rake", ">= 12") - spec.add_development_dependency("rdoc", ">= 3.12") + spec.add_development_dependency("appraisal", "~> 2.5") + spec.add_development_dependency("json", ">= 1.7.7") + spec.add_development_dependency("rake", ">= 0.8.7") + spec.add_development_dependency("rdoc", ">= 3") spec.add_development_dependency("rspec", ">= 3") spec.add_development_dependency("rspec-block_is_expected", "~> 1.0", ">= 1.0.5") spec.add_development_dependency("rspec-pending_for", "~> 0.1", ">= 0.1.16") diff --git a/spec/internal/app/assets/config/manifest.js b/spec/internal/app/assets/config/manifest.js new file mode 100644 index 0000000..e69de29 diff --git a/spec/internal/config/database.yml b/spec/internal/config/database.yml new file mode 100644 index 0000000..b978119 --- /dev/null +++ b/spec/internal/config/database.yml @@ -0,0 +1,3 @@ +test: + adapter: sqlite3 + database: db/combustion_test.sqlite diff --git a/spec/internal/config/routes.rb b/spec/internal/config/routes.rb new file mode 100644 index 0000000..878c813 --- /dev/null +++ b/spec/internal/config/routes.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +Rails.application.routes.draw do + # Add your own routes here, or remove this file if you don't have need for it. +end diff --git a/spec/internal/config/storage.yml b/spec/internal/config/storage.yml new file mode 100644 index 0000000..62da734 --- /dev/null +++ b/spec/internal/config/storage.yml @@ -0,0 +1,3 @@ +test: + service: Disk + root: /Users/pboling/src/my/sanitize_email/tmp/storage diff --git a/spec/internal/db/schema.rb b/spec/internal/db/schema.rb new file mode 100644 index 0000000..3b396d0 --- /dev/null +++ b/spec/internal/db/schema.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +ActiveRecord::Schema.define do + # Set up any tables you need to exist for your test suite that don't belong + # in migrations. +end diff --git a/spec/internal/log/.gitignore b/spec/internal/log/.gitignore new file mode 100644 index 0000000..bf0824e --- /dev/null +++ b/spec/internal/log/.gitignore @@ -0,0 +1 @@ +*.log \ No newline at end of file diff --git a/spec/internal/public/favicon.ico b/spec/internal/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb new file mode 100644 index 0000000..198dd63 --- /dev/null +++ b/spec/rails_helper.rb @@ -0,0 +1,25 @@ +require "spec_helper" +ENV["RAILS_ENV"] ||= "test" + +# Last thing before loading this gem is to setup code coverage +begin + # This does not require "simplecov", but + require "kettle-soup-cover" + # this next line has a side-effect of running `.simplecov` + require "simplecov" if defined?(Kettle::Soup::Cover) && Kettle::Soup::Cover::DO_COV +rescue LoadError + nil +end + +require "bundler" +Bundler.require :default, :development +Combustion.initialize! :action_mailer, :action_controller + +puts "Rails version is #{Rails.version}" +puts "BUNDLE_GEMFILE: #{ENV["BUNDLE_GEMFILE"]}" +puts "RAILS_VERSION: #{ENV["RAILS_VERSION"]}" +puts "RAILS_MAJOR_MINOR: #{ENV["RAILS_MAJOR_MINOR"]}" + +# require "rspec/rails" + +require "sanitize_email" diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb new file mode 100644 index 0000000..c6cb3a9 --- /dev/null +++ b/spec/rails_spec.rb @@ -0,0 +1,14 @@ +RSpec.describe Rails do + expected_rails_version = ENV.fetch("RAILS_MAJOR_MINOR", nil) + actual_rails_version = "#{described_class::VERSION::MAJOR}.#{described_class::VERSION::MINOR}" + if expected_rails_version.nil? + it "has Rails Version (default, 7.1) matching actual #{actual_rails_version}" do + # When not otherwise set, Rails should be 7.1 + expect(actual_rails_version).to match("7.1") + end + else + it "has Rails Version (custom from ENV, #{expected_rails_version}) matching actual #{actual_rails_version}" do + expect(actual_rails_version).to eq(expected_rails_version) + end + end +end diff --git a/spec/sanitize_email_spec.rb b/spec/sanitize_email_spec.rb index a97b6c2..d368519 100644 --- a/spec/sanitize_email_spec.rb +++ b/spec/sanitize_email_spec.rb @@ -25,7 +25,11 @@ def sanitize_spec_dryer(rails_env = "test") end Mail.defaults do - delivery_method :logger, logger: logger, severity: :info + if Rails::VERSION::MAJOR == 3 + delivery_method :test + else + delivery_method :logger, logger: logger, severity: :info + end end SanitizeEmail::Config.instance_variable_set( :@config, @@ -202,7 +206,7 @@ def mail_delivery_multiple_personalizations context "module methods" do describe ":[]" do it "accesses config" do - expect(SanitizeEmail[:environment]).to eq("[development]") + expect(SanitizeEmail[:environment]).to eq("[test]") end it "does not raise on non-responsive to :to_sym" do @@ -216,7 +220,7 @@ def mail_delivery_multiple_personalizations describe ":method_missing" do it "accesses config" do - expect(SanitizeEmail.environment).to eq("[development]") + expect(SanitizeEmail.environment).to eq("[test]") end it "does not raise on unknown method" do @@ -712,49 +716,62 @@ def mail_delivery_multiple_personalizations environment: "## CHEW-GRUEL ##", use_actual_environment_prepended_to_subject: true, ) - expect { mail_delivery_multiple_personalizations }.not_to raise_exception - expect(@email_message).to have_to("to@sanitize_email.org") - expect(@email_message).to have_cc("cc@sanitize_email.org") - expect(@email_message).to have_bcc("bcc@sanitize_email.org") - expect(@email_message).to have_from("from@example.org") - expect(@email_message).to have_subject("## CHEW-GRUEL ## original subject") - expect(@email_message).to have_reply_to("reply_to@example.org") - expect(@email_message).to have_body_text("funky fresh") - expect(@email_message).to have_header( - "X-Sanitize-Email-To", - "to1@example.org", - ) - expect(@email_message).to have_header( - "X-Sanitize-Email-To-2", - "to2@example.org", - ) - expect(@email_message).to have_header( - "X-Sanitize-Email-To-3", - "to3@example.org", - ) - expect(@email_message).to have_header( - "X-Sanitize-Email-Cc", - "cc1@example.org", - ) - expect(@email_message).to have_header( - "X-Sanitize-Email-Cc-2", - "cc2@example.org", - ) - expect(@email_message).to have_header( - "X-Sanitize-Email-Cc-3", - "cc3@example.org", - ) + if Rails::VERSION::MAJOR == 3 + expect { + mail_delivery_multiple_personalizations + }.to raise_exception( + SanitizeEmail::OverriddenAddresses::MissingRecipients, + "Mail version is too old to use personalizations", + ) + else + expect { mail_delivery_multiple_personalizations }.not_to raise_exception + expect(@email_message).to have_to("to@sanitize_email.org") + expect(@email_message).to have_cc("cc@sanitize_email.org") + expect(@email_message).to have_bcc("bcc@sanitize_email.org") + expect(@email_message).to have_from("from@example.org") + expect(@email_message).to have_subject("## CHEW-GRUEL ## original subject") + expect(@email_message).to have_reply_to("reply_to@example.org") + expect(@email_message).to have_body_text("funky fresh") + expect(@email_message).to have_header( + "X-Sanitize-Email-To", + "to1@example.org", + ) + expect(@email_message).to have_header( + "X-Sanitize-Email-To-2", + "to2@example.org", + ) + expect(@email_message).to have_header( + "X-Sanitize-Email-To-3", + "to3@example.org", + ) + expect(@email_message).to have_header( + "X-Sanitize-Email-Cc", + "cc1@example.org", + ) + expect(@email_message).to have_header( + "X-Sanitize-Email-Cc-2", + "cc2@example.org", + ) + expect(@email_message).to have_header( + "X-Sanitize-Email-Cc-3", + "cc3@example.org", + ) + end end end context "with activation_proc enabling" do - it "activates" do + subject(:with_activation_proc) { configure_sanitize_email( activation_proc: proc { true }, environment: "## CHEW-GRUEL ##", use_actual_environment_prepended_to_subject: true, ) - expect { mail_delivery }.not_to raise_exception + mail_delivery + } + + it "activates" do + block_is_expected.not_to raise_exception expect(@email_message).to have_to("to@sanitize_email.org") expect(@email_message).to have_cc("cc@sanitize_email.org") expect(@email_message).to have_bcc("bcc@sanitize_email.org") diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b6dd710..28b481f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,9 +3,6 @@ # Copyright (c) 2008 - 2018, 2020, 2022, 2024 Peter H. Boling of RailsBling.com # Released under the MIT license -require "rails" -require "action_mailer" -require "logger" require "rspec/pending_for" # RSpec Configs @@ -14,15 +11,3 @@ require "config/rspec/rspec_core" require "config/rspec/version_gem" require "support/matchers" - -# Last thing before loading this gem is to setup code coverage -begin - # This does not require "simplecov", but - require "kettle-soup-cover" - # this next line has a side-effect of running `.simplecov` - require "simplecov" if defined?(Kettle::Soup::Cover) && Kettle::Soup::Cover::DO_COV -rescue LoadError - nil -end - -require "sanitize_email"