as_deprecation_tracker 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b25a9c470b3310b7a3112d290e0655811ea93c3d
4
+ data.tar.gz: 78857eba82e956ad61ad8e6276128fe4a73d6056
5
+ SHA512:
6
+ metadata.gz: 83efcef8a382e9c9cace6a2e942f7d96032d587b76b1ab36707cf3f7c37c82a1e6a8a241c1bdd8da5de298fe6e5ec2b2f705414f8c47208d3581059087629e0e
7
+ data.tar.gz: c6558bacefd24acba76e6aa3e6bb23beff1e26cf1ec502cc010f6172f7cdd07f86affaf919509eef9b58015fb2ab7d3e761b129b16800765684a422b9aa7b94d
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2016 Dominic Cleal
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # as_deprecation_tracker
2
+
3
+ Tracks known ActiveSupport (Rails) deprecation warnings and catches new issues
4
+ when an unknown warning is seen.
5
+
6
+ This allows for easier upgrades of Rails and other AS-based apps because as
7
+ each deprecation warning is fixed, it's removed from the whitelist and any
8
+ attempt to reintroduce the deprecated call will fail. It's also useful when the
9
+ app runs on multiple versions of Rails and newer deprecation warnings can't be
10
+ fixed yet without breaking the older version.
11
+
12
+ The library maintains the whitelist in a configuration file that's usually
13
+ initially written by running the app test suite with an environment variable
14
+ set. When the tests are run normally, deprecation warnings triggered that
15
+ aren't in the config file will raise an exception. The call can then be fixed
16
+ or added to the whitelist with the provided instructions.
17
+
18
+ If you'd prefer just to fix all deprecation warnings at once then this gem is
19
+ unnecessary! Just use:
20
+
21
+ ```ruby
22
+ ActiveSupport::Deprecation.behavior = :raise
23
+ ```
24
+
25
+ in your test environment config.
26
+
27
+ ## Installation
28
+
29
+ $ gem install as_deprecation_tracker
30
+
31
+ or in your Gemfile:
32
+
33
+ gem 'as_deprecation_tracker', '~> 1.0', group: 'test'
34
+
35
+ This gem and its API is versioned according to semver.
36
+
37
+ It's recommended to only add the gem to the test Bundler group as raising
38
+ errors in production and development isn't desirable.
39
+
40
+ ## Usage
41
+
42
+ ### Automatic whitelisting
43
+
44
+ To set up an initial whitelist, run:
45
+
46
+ AS_DEPRECATION_RECORD=yes bin/rake test
47
+
48
+ This will generate `config/as_deprecation_whitelist.yaml` with a list of
49
+ specific instances of deprecated calls which can be committed. Subsequent `rake
50
+ test` runs will then automatically raise errors for new occurrences.
51
+
52
+ Re-run tests with `AS_DEPRECATION_RECORD=yes` to append new instances to the
53
+ existing configuration file, if you wish to whitelist rather than fix them.
54
+
55
+ ### Whitelist configuration
56
+
57
+ The whitelist may be broad, permitting any call causing a particular
58
+ deprecation message or be precise, only permitting known calls identified by
59
+ their backtrace. With broad whitelists, more instances of the same deprecated
60
+ call may be added, but precise whitelists require more maintenance if code is
61
+ moved and the backtrace changes.
62
+
63
+ The whitelist is stored in the Rails root at
64
+ `config/as_deprecation_whitelist.yaml` and is a YAML file containing a single
65
+ array of hashes:
66
+
67
+ ```yaml
68
+ ---
69
+ - message: "Deprecated call to X, use Y instead"
70
+ - message: "Deprecated call to Z"
71
+ callstack: "app/models/foo.rb:23:in `example_method'"
72
+ ```
73
+
74
+ Accepted keys are `message`, matching the exact deprecation message and
75
+ `callstack`, a string or an array forming the backtrace of the deprecation.
76
+ If an array is given for the callstack, all entries must match the caller.
77
+
78
+ The callstack will match on as much data as is provided - if only a file is
79
+ given, any matching deprecation within the file will be whitelisted. The line
80
+ number and method specification may be given for more specificity. The line
81
+ number may vary by up to ten lines from the recorded number by default (see
82
+ `line_tolerance` to tune). Usually the filename and method name are sufficient
83
+ to match the caller without needing line numbers.
84
+
85
+ ### Configuration
86
+
87
+ Use an initializer to change ASDT's behaviour at startup:
88
+
89
+ ```ruby
90
+ ASDeprecationTracker.config.envs = %w(test development)
91
+ ```
92
+
93
+ Supported options:
94
+
95
+ * `envs` is an array of string Rails environment names that ASDT will monitor
96
+ and raise errors for unpermitted deprecation warnings (defaults to
97
+ `['test']`)
98
+ * `line_tolerance` is the number of lines that callstack line numbers may
99
+ differ from the deprecated call (defaults to 10)
100
+ * `register_behavior` controls whether to change the AS::Deprecation behavior
101
+ to ASDeprecationTracker::Receiver at startup, may be disabled to use multiple
102
+ behaviors (defaults to true)
103
+ * `whitelist_file` to customise the location of the whitelist YAML file
104
+ (defaults to `config/as_deprecation_whitelist.yaml` beneath the Rails root)
105
+
106
+ ## License
107
+
108
+ Copyright (c) 2016 Dominic Cleal. Distributed under the MIT license.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ require 'bundler/gem_tasks'
3
+ require 'rake/testtask'
4
+ require 'rubocop/rake_task'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'test'
8
+ t.test_files = FileList['test/*_test.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ RuboCop::RakeTask.new
13
+
14
+ task default: %w(rubocop test)
data/config.ru ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require 'rubygems'
3
+ require 'bundler'
4
+
5
+ Bundler.require :default, :development
6
+
7
+ Combustion.initialize! :all
8
+ run Combustion::Application
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module ASDeprecationTracker
3
+ # Maintains configuration for one instance (usually global)
4
+ class Configuration
5
+ attr_accessor :envs, :line_tolerance, :register_behavior, :whitelist_file
6
+ alias register_behavior? register_behavior
7
+
8
+ def initialize
9
+ @envs = %w(test)
10
+ @line_tolerance = 10
11
+ @register_behavior = true
12
+ @whitelist_file = File.join(Rails.root, 'config', 'as_deprecation_whitelist.yaml')
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ require 'as_deprecation_tracker/receiver'
3
+
4
+ module ASDeprecationTracker
5
+ # Railtie to register for deprecation notifications
6
+ class Railtie < ::Rails::Railtie
7
+ initializer 'as_deprecation_tracker.deprecation_notifications', after: :load_environment_config, if: -> { ASDeprecationTracker.active? } do
8
+ Receiver.attach_to :rails
9
+ ActiveSupport::Deprecation.behavior = :notify if ASDeprecationTracker.config.register_behavior?
10
+
11
+ whitelist = ASDeprecationTracker.config.whitelist_file
12
+ ASDeprecationTracker.whitelist.load_file(whitelist) if File.exist?(whitelist)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+ require 'active_support/subscriber'
3
+ require 'as_deprecation_tracker/writer'
4
+
5
+ module ASDeprecationTracker
6
+ # Receives deprecation.rails events via ActiveSupport::Notifications
7
+ class Receiver < ::ActiveSupport::Subscriber
8
+ def deprecation(event)
9
+ return if ASDeprecationTracker.whitelist.matches?(event.payload)
10
+
11
+ message = event.payload[:message]
12
+ callstack = event.payload[:callstack].map(&:to_s)
13
+ if ENV['AS_DEPRECATION_RECORD'].present?
14
+ write_deprecation(message, callstack)
15
+ else
16
+ raise_deprecation(message, callstack)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def write_deprecation(message, callstack)
23
+ writer = ASDeprecationTracker::Writer.new(ASDeprecationTracker.config.whitelist_file)
24
+ writer.add(message, callstack)
25
+ writer.write_file
26
+ end
27
+
28
+ def raise_deprecation(message, callstack)
29
+ e = ActiveSupport::DeprecationException.new(message)
30
+ e.set_backtrace(callstack)
31
+ raise e
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ module ASDeprecationTracker
3
+ VERSION = '1.0.0'.freeze
4
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ require 'as_deprecation_tracker/whitelist_entry'
3
+
4
+ module ASDeprecationTracker
5
+ # Stores a list of known and ignored deprecation warnings, and provides a
6
+ # query interface to check if a warning matches the list
7
+ class Whitelist
8
+ attr_reader :list
9
+
10
+ def initialize
11
+ @list = []
12
+ end
13
+
14
+ def add_to_list(entries)
15
+ entries.each { |entry| @list << WhitelistEntry.new(entry) }
16
+ end
17
+
18
+ def clear
19
+ @list.clear
20
+ end
21
+
22
+ def load_file(path)
23
+ add_to_list(YAML.load(File.read(path)))
24
+ end
25
+
26
+ def matches?(deprecation)
27
+ @list.any? { |entry| entry.matches?(deprecation) }
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+ module ASDeprecationTracker
3
+ # Configuration of a whitelisted (known) deprecation warning matched by data
4
+ # such as a message and/or callstack
5
+ class WhitelistEntry
6
+ MESSAGE_CLEANUP_RE = Regexp.new('\ADEPRECATION WARNING: (.+) \(called from.*')
7
+ CALLSTACK_FILE_RE = Regexp.new('\A(.*?)(?::(\d+))?(?::in `(.+)\')?\z')
8
+
9
+ def initialize(entry)
10
+ entry = entry.with_indifferent_access
11
+ raise('Missing `message` or `callstack` from whitelist entry') unless entry.key?(:message) || entry.key?(:callstack)
12
+ @message = entry[:message]
13
+ @callstack = callstack_to_files_lines(Array.wrap(entry[:callstack]))
14
+ end
15
+
16
+ def matches?(deprecation)
17
+ return false if @message.present? && !message_matches?(deprecation[:message])
18
+ return false if @callstack.present? && !callstack_matches?(deprecation[:callstack])
19
+ true
20
+ end
21
+
22
+ private
23
+
24
+ def message_matches?(message)
25
+ cleanup_match = MESSAGE_CLEANUP_RE.match(message)
26
+ message = cleanup_match[1] if cleanup_match
27
+ message == @message
28
+ end
29
+
30
+ def callstack_to_files_lines(callstack)
31
+ callstack.map do |entry|
32
+ file_match = CALLSTACK_FILE_RE.match(entry)
33
+ [file_match[1], file_match[2].nil? ? nil : file_match[2].to_i, file_match[3]]
34
+ end
35
+ end
36
+
37
+ def callstack_matches?(callstack)
38
+ callstack = callstack_to_files_lines(callstack)
39
+
40
+ @callstack.all? do |whitelist_entry|
41
+ callstack_entry_matches?(whitelist_entry, callstack)
42
+ end
43
+ end
44
+
45
+ def callstack_entry_matches?(whitelist_entry, callstack)
46
+ callstack.any? do |callstack_entry|
47
+ callstack_entry[0] == whitelist_entry[0] &&
48
+ line_number_within_tolerance(callstack_entry[1], whitelist_entry[1]) &&
49
+ method_name_matches(callstack_entry[2], whitelist_entry[2])
50
+ end
51
+ end
52
+
53
+ def line_number_within_tolerance(line1, line2)
54
+ return true if line1.nil? || line2.nil?
55
+ (line1 - line2).abs <= ASDeprecationTracker.config.line_tolerance
56
+ end
57
+
58
+ def method_name_matches(method1, method2)
59
+ return true if method1.nil? || method2.nil?
60
+ method1 == method2
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+ require 'as_deprecation_tracker/whitelist_entry'
3
+ require 'rails/backtrace_cleaner'
4
+
5
+ module ASDeprecationTracker
6
+ # Rewrites the whitelist configuration file to append new observed entries
7
+ class Writer
8
+ def initialize(filename)
9
+ @filename = filename
10
+ @contents = []
11
+ @contents = YAML.load(File.read(filename)) || [] if File.exist?(filename)
12
+ end
13
+
14
+ def add(message, callstack)
15
+ cleanup_match = WhitelistEntry::MESSAGE_CLEANUP_RE.match(message)
16
+ message = cleanup_match[1] if cleanup_match
17
+
18
+ callstack = Rails::BacktraceCleaner.new.clean(callstack, :silent)
19
+
20
+ @contents << { 'message' => message, 'callstack' => callstack.first }
21
+ end
22
+
23
+ def contents
24
+ @contents.sort_by { |e| e.values_at('message', 'callstack') }.to_yaml
25
+ end
26
+
27
+ def write_file
28
+ File.write(@filename, contents)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ # Entry point, provides constant with access to global configuration only
3
+ module ASDeprecationTracker
4
+ require 'as_deprecation_tracker/configuration'
5
+ require 'as_deprecation_tracker/railtie'
6
+ require 'as_deprecation_tracker/version'
7
+ require 'as_deprecation_tracker/whitelist'
8
+
9
+ def self.active?
10
+ config.envs.include?(Rails.env)
11
+ end
12
+
13
+ def self.config
14
+ @config ||= Configuration.new
15
+ end
16
+
17
+ def self.whitelist
18
+ @whitelist ||= Whitelist.new
19
+ end
20
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ class ASDeprecationTrackerTest < ASDeprecationTracker::TestCase
5
+ def test_active?
6
+ assert ASDeprecationTracker.active?
7
+ end
8
+
9
+ def test_active_in_other_env
10
+ ASDeprecationTracker.expects(:config).twice.returns(ASDeprecationTracker::Configuration.new)
11
+ ASDeprecationTracker.config.envs = ['development']
12
+ refute ASDeprecationTracker.active?
13
+ end
14
+
15
+ def test_config
16
+ assert_kind_of ASDeprecationTracker::Configuration, ASDeprecationTracker.config
17
+ end
18
+
19
+ def test_config_returns_same_configuration
20
+ config = ASDeprecationTracker.config
21
+ assert_equal config, ASDeprecationTracker.config
22
+ end
23
+
24
+ def test_whitelist
25
+ assert_kind_of ASDeprecationTracker::Whitelist, ASDeprecationTracker.whitelist
26
+ end
27
+
28
+ def test_whitelist_returns_same_whitelist
29
+ whitelist = ASDeprecationTracker.whitelist
30
+ assert_equal whitelist, ASDeprecationTracker.whitelist
31
+ end
32
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ class ConfigurationTest < ASDeprecationTracker::TestCase
5
+ def setup
6
+ @config = ASDeprecationTracker::Configuration.new
7
+ super
8
+ end
9
+
10
+ def test_envs
11
+ assert_equal ['test'], @config.envs
12
+ end
13
+
14
+ def test_envs=
15
+ @config.envs = ['development']
16
+ assert_equal ['development'], @config.envs
17
+ end
18
+
19
+ def test_line_tolerance
20
+ assert_equal 10, @config.line_tolerance
21
+ end
22
+
23
+ def test_line_tolerance=
24
+ @config.line_tolerance = 42
25
+ assert_equal 42, @config.line_tolerance
26
+ end
27
+
28
+ def test_register_behavior?
29
+ assert_equal true, @config.register_behavior?
30
+ end
31
+
32
+ def test_register_behavior=
33
+ @config.register_behavior = false
34
+ assert_equal false, @config.register_behavior?
35
+ end
36
+
37
+ def test_whitelist_file
38
+ assert_kind_of String, @config.whitelist_file
39
+ assert File.exist?(@config.whitelist_file)
40
+ end
41
+
42
+ def test_whitelist_file=
43
+ @config.whitelist_file = 'another_file.yaml'
44
+ assert_equal 'another_file.yaml', @config.whitelist_file
45
+ end
46
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ Rails.application.routes.draw do
3
+ #
4
+ end
@@ -0,0 +1 @@
1
+ *.log
File without changes
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ class RailtieTest < ASDeprecationTracker::TestCase
5
+ def test_deprecation_behavior
6
+ assert_equal [ActiveSupport::Deprecation::DEFAULT_BEHAVIORS[:notify]], ActiveSupport::Deprecation.behavior
7
+ end
8
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ class ReceiverTest < ASDeprecationTracker::TestCase
5
+ def test_deprecation_whitelisted
6
+ whitelist = ASDeprecationTracker::Whitelist.new
7
+ ASDeprecationTracker.expects(:whitelist).returns(whitelist)
8
+ stack = caller
9
+ whitelist.expects(:matches?).with(message: 'deprecated call', callstack: stack).returns(true)
10
+ ASDeprecationTracker::Receiver.new.deprecation(event(message: 'deprecated call', callstack: stack))
11
+ end
12
+
13
+ def test_deprecation_unknown
14
+ whitelist = ASDeprecationTracker::Whitelist.new
15
+ ASDeprecationTracker.expects(:whitelist).returns(whitelist)
16
+ stack = caller
17
+ whitelist.expects(:matches?).with(message: 'deprecated call', callstack: stack).returns(false)
18
+ e = assert_raises(ActiveSupport::DeprecationException) do
19
+ ASDeprecationTracker::Receiver.new.deprecation(event(message: 'deprecated call', callstack: stack))
20
+ end
21
+ assert_equal 'deprecated call', e.message
22
+ assert_equal stack, e.backtrace
23
+ end
24
+
25
+ def test_deprecation_unknown_record
26
+ whitelist = ASDeprecationTracker::Whitelist.new
27
+ ASDeprecationTracker.expects(:whitelist).returns(whitelist)
28
+ stack = caller
29
+ whitelist.expects(:matches?).with(message: 'deprecated call', callstack: stack).returns(false)
30
+ ASDeprecationTracker::Writer.any_instance.expects(:add).with('deprecated call', stack)
31
+ ASDeprecationTracker::Writer.any_instance.expects(:write_file)
32
+ ENV['AS_DEPRECATION_RECORD'] = 'true'
33
+ ASDeprecationTracker::Receiver.new.deprecation(event(message: 'deprecated call', callstack: stack))
34
+ ensure
35
+ ENV.delete('AS_DEPRECATION_RECORD')
36
+ end
37
+
38
+ def test_subscription
39
+ ASDeprecationTracker::Receiver.any_instance.expects(:deprecation)
40
+ ActiveSupport::Notifications.instrument('deprecation.rails', message: 'test')
41
+ end
42
+
43
+ private
44
+
45
+ def event(payload)
46
+ mock('event').tap do |event|
47
+ event.stubs(:payload).returns(payload)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ require 'minitest/autorun'
3
+ require 'mocha/mini_test'
4
+ require 'combustion'
5
+
6
+ require 'as_deprecation_tracker'
7
+
8
+ Combustion.path = 'test/internal'
9
+ Combustion.initialize!
10
+
11
+ module ASDeprecationTracker
12
+ class TestCase < ::Minitest::Test; end
13
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ class WhitelistEntryTest < ASDeprecationTracker::TestCase
5
+ def test_initialize_with_strings
6
+ ASDeprecationTracker::WhitelistEntry.new('message' => 'test')
7
+ end
8
+
9
+ def test_initialize_with_symbols
10
+ ASDeprecationTracker::WhitelistEntry.new(message: 'test')
11
+ end
12
+
13
+ def test_matches_message_and_callstack
14
+ assert entry.matches?(deprecation)
15
+ end
16
+
17
+ def test_matches_message_with_surrounding_content
18
+ assert entry.matches?(deprecation(message: 'DEPRECATION WARNING: uniq is deprecated and will be removed (called from block in <class:Foo> at app/models/foo.rb:23)'))
19
+ end
20
+
21
+ def test_matches_message_only
22
+ assert entry(callstack: nil).matches?(deprecation(callstack: caller))
23
+ end
24
+
25
+ def test_matches_callstack_only
26
+ assert entry(message: nil).matches?(deprecation)
27
+ end
28
+
29
+ def test_matches_partial_callstack_top
30
+ assert entry(callstack: ['/home/user/app/models/foo.rb:23']).matches?(deprecation)
31
+ end
32
+
33
+ def test_matches_partial_callstack_bottom
34
+ assert entry(callstack: ['/home/user/app/controllers/foos_controller.rb:42']).matches?(deprecation)
35
+ end
36
+
37
+ def test_matches_partial_callstack_multiple
38
+ assert entry(callstack: [
39
+ '/home/user/app/models/foo.rb:23',
40
+ '/home/user/app/controllers/foos_controller.rb:42'
41
+ ]).matches?(deprecation)
42
+ end
43
+
44
+ def test_matches_partial_callstack_within_tolerance
45
+ assert entry(callstack: ['/home/user/app/models/foo.rb:25']).matches?(deprecation)
46
+ end
47
+
48
+ def test_matches_partial_callstack_outside_tolerance
49
+ refute entry(callstack: ['/home/user/app/models/foo.rb:34']).matches?(deprecation)
50
+ end
51
+
52
+ def test_matches_partial_callstack_same_method
53
+ assert entry(callstack: ['/home/user/app/models/foo.rb:in `example_method\'']).matches?(deprecation)
54
+ end
55
+
56
+ def test_matches_partial_callstack_different_method
57
+ refute entry(callstack: ['/home/user/app/models/foo.rb:23:in `another_method\'']).matches?(deprecation)
58
+ end
59
+
60
+ def test_matches_partial_callstack_different_method_no_line
61
+ refute entry(callstack: ['/home/user/app/models/foo.rb:in `another_method\'']).matches?(deprecation)
62
+ end
63
+
64
+ def test_matches_partial_callstack_within_tolerance_same_method
65
+ assert entry(callstack: ['/home/user/app/models/foo.rb:25:in `example_method\'']).matches?(deprecation)
66
+ end
67
+
68
+ def test_matches_partial_callstack_outside_tolerance_same_method
69
+ refute entry(callstack: ['/home/user/app/models/foo.rb:34:in `example_method\'']).matches?(deprecation)
70
+ end
71
+
72
+ def test_matches_partial_callstack_string
73
+ assert entry(callstack: '/home/user/app/models/foo.rb:23').matches?(deprecation)
74
+ end
75
+
76
+ def test_matches_partial_callstack_file
77
+ assert entry(callstack: ['/home/user/app/models/foo.rb']).matches?(deprecation)
78
+ end
79
+
80
+ def test_matches_different_message_same_callstack
81
+ refute entry.matches?(deprecation(message: 'a different method is deprecated'))
82
+ end
83
+
84
+ def test_matches_same_message_different_callstack
85
+ refute entry.matches?(deprecation(callstack: caller))
86
+ end
87
+
88
+ def test_matches_different_message_different_callstack
89
+ refute entry.matches?(deprecation(message: 'a different method is deprecated', callstack: caller))
90
+ end
91
+
92
+ private
93
+
94
+ def deprecation(overrides = {})
95
+ {
96
+ message: 'uniq is deprecated and will be removed',
97
+ callstack: [
98
+ '/home/user/app/models/foo.rb:23:in `example_method\'',
99
+ '/home/user/app/controllers/foos_controller.rb:42:in `update\'',
100
+ '/home/user/test/controllers/foos_controller_test.rb:18:in `block in <class:FoosControllerTest>\''
101
+ ]
102
+ }.merge(overrides).compact
103
+ end
104
+
105
+ def entry(overrides = {})
106
+ ASDeprecationTracker::WhitelistEntry.new(deprecation(overrides))
107
+ end
108
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ class WhitelistTest < ASDeprecationTracker::TestCase
5
+ def setup
6
+ @whitelist = ASDeprecationTracker::Whitelist.new
7
+ super
8
+ end
9
+
10
+ def test_add_to_list
11
+ @whitelist.add_to_list([entry])
12
+ assert_equal 1, @whitelist.list.count
13
+ end
14
+
15
+ def test_clear
16
+ @whitelist.add_to_list([entry])
17
+ @whitelist.clear
18
+ assert @whitelist.list.empty?
19
+ end
20
+
21
+ def test_load_file
22
+ File.expects(:read).with('root/config/as_deprecation_whitelist.yaml').returns("---\n- :message: test\n")
23
+ @whitelist.load_file('root/config/as_deprecation_whitelist.yaml')
24
+ assert_equal 1, @whitelist.list.count
25
+ end
26
+
27
+ def test_matches_failure
28
+ @whitelist.add_to_list([entry])
29
+ deprecation = mock('deprecation')
30
+ @whitelist.list.first.expects(:matches?).with(deprecation).returns(false)
31
+ refute @whitelist.matches?(deprecation)
32
+ end
33
+
34
+ def test_matches_success
35
+ @whitelist.add_to_list([entry])
36
+ deprecation = mock('deprecation')
37
+ @whitelist.list.first.expects(:matches?).with(deprecation).returns(true)
38
+ assert @whitelist.matches?(deprecation)
39
+ end
40
+
41
+ private
42
+
43
+ def entry
44
+ { message: 'deprecated call', callstack: caller }
45
+ end
46
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ class WriterTest < ASDeprecationTracker::TestCase
5
+ def test_add
6
+ writer = new_writer
7
+ writer.add('deprecated call', ['app/models/a.rb:23', 'app/models/b.rb:42'])
8
+ assert_equal [{ 'message' => 'deprecated call', 'callstack' => 'app/models/a.rb:23' }], YAML.load(writer.contents)
9
+ end
10
+
11
+ def test_add_strips_surrounding
12
+ writer = new_writer
13
+ writer.add('DEPRECATION WARNING: deprecated call (called from app/models/a.rb:23)', ['app/models/a.rb:23', 'app/models/b.rb:42'])
14
+ assert_equal [{ 'message' => 'deprecated call', 'callstack' => 'app/models/a.rb:23' }], YAML.load(writer.contents)
15
+ end
16
+
17
+ def test_add_cleans_callstack
18
+ writer = new_writer
19
+ Gem.expects(:path).returns(['/home/user/.rvm/gems/ruby-2.3.0'])
20
+ writer.add('deprecated call', ['/home/user/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/relation/finder_methods.rb:280:in `exists?\'', 'app/models/a.rb:23', 'app/models/b.rb:42'])
21
+ assert_equal [{ 'message' => 'deprecated call', 'callstack' => 'app/models/a.rb:23' }], YAML.load(writer.contents)
22
+ end
23
+
24
+ def test_contents_new_file_is_array
25
+ assert_equal [], YAML.load(new_writer('').contents)
26
+ end
27
+
28
+ def test_contents_sorting
29
+ writer = new_writer
30
+ writer.add('deprecated call 1', ['app/models/a.rb:42', 'app/models/b.rb:42'])
31
+ writer.add('deprecated call 2', ['app/models/a.rb:23', 'app/models/b.rb:42'])
32
+ writer.add('deprecated call 1', ['app/models/a.rb:23', 'app/models/b.rb:42'])
33
+ assert_equal [
34
+ { 'message' => 'deprecated call 1', 'callstack' => 'app/models/a.rb:23' },
35
+ { 'message' => 'deprecated call 1', 'callstack' => 'app/models/a.rb:42' },
36
+ { 'message' => 'deprecated call 2', 'callstack' => 'app/models/a.rb:23' }
37
+ ], YAML.load(writer.contents)
38
+ end
39
+
40
+ def test_write_file
41
+ writer = new_writer
42
+ writer.expects(:contents).returns('--- []')
43
+ File.expects(:write).with('root/config/as_deprecation_whitelist.yaml', '--- []')
44
+ writer.write_file
45
+ end
46
+
47
+ private
48
+
49
+ def new_writer(input = '')
50
+ File.expects(:exist?).with('root/config/as_deprecation_whitelist.yaml').returns(true)
51
+ File.expects(:read).with('root/config/as_deprecation_whitelist.yaml').returns(input)
52
+ ASDeprecationTracker::Writer.new('root/config/as_deprecation_whitelist.yaml')
53
+ end
54
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: as_deprecation_tracker
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Dominic Cleal
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-11-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: railties
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '4.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '4.2'
41
+ description: Tracks known ActiveSupport (Rails) deprecation warnings and catches new
42
+ issues when an unknown warning is seen.
43
+ email: dominic@cleal.org
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - LICENSE
49
+ - README.md
50
+ - Rakefile
51
+ - config.ru
52
+ - lib/as_deprecation_tracker.rb
53
+ - lib/as_deprecation_tracker/configuration.rb
54
+ - lib/as_deprecation_tracker/railtie.rb
55
+ - lib/as_deprecation_tracker/receiver.rb
56
+ - lib/as_deprecation_tracker/version.rb
57
+ - lib/as_deprecation_tracker/whitelist.rb
58
+ - lib/as_deprecation_tracker/whitelist_entry.rb
59
+ - lib/as_deprecation_tracker/writer.rb
60
+ - test/as_deprecation_tracker_test.rb
61
+ - test/configuration_test.rb
62
+ - test/internal/config/as_deprecation_whitelist.yaml
63
+ - test/internal/config/routes.rb
64
+ - test/internal/log/.gitignore
65
+ - test/internal/public/favicon.ico
66
+ - test/railtie_test.rb
67
+ - test/receiver_test.rb
68
+ - test/test_helper.rb
69
+ - test/whitelist_entry_test.rb
70
+ - test/whitelist_test.rb
71
+ - test/writer_test.rb
72
+ homepage: https://github.com/domcleal/as_deprecation_tracker
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 2.0.0
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.6.8
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: Track known ActiveSupport deprecation warnings
96
+ test_files: []