shoulda-matchers 2.6.1 → 2.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +9 -0
- data/.yardopts +8 -0
- data/Appraisals +82 -33
- data/Gemfile +18 -2
- data/Gemfile.lock +13 -1
- data/NEWS.md +27 -2
- data/README.md +83 -1329
- data/Rakefile +118 -1
- data/cucumber.yml +1 -0
- data/doc_config/gh-pages/index.html.erb +9 -0
- data/doc_config/yard/setup.rb +22 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +5967 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +12 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/global.css +45 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +69 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/style.css +283 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +32 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +1 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +8 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/app.js +298 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +1 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +289 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +6 -0
- data/doc_config/yard/templates/default/fulldoc/html/setup.rb +8 -0
- data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +14 -0
- data/doc_config/yard/templates/default/layout/html/fonts.erb +1 -0
- data/doc_config/yard/templates/default/layout/html/layout.erb +23 -0
- data/doc_config/yard/templates/default/layout/html/search.erb +13 -0
- data/doc_config/yard/templates/default/layout/html/setup.rb +40 -0
- data/doc_config/yard/templates/default/method_details/html/source.erb +10 -0
- data/doc_config/yard/templates/default/module/html/box_info.erb +31 -0
- data/docs.watchr +5 -0
- data/features/rails_integration.feature +32 -0
- data/features/step_definitions/rails_steps.rb +55 -9
- data/features/support/env.rb +1 -0
- data/gemfiles/3.0.gemfile +13 -1
- data/gemfiles/3.0.gemfile.lock +13 -1
- data/gemfiles/3.1.gemfile +17 -2
- data/gemfiles/3.1.gemfile.lock +31 -2
- data/gemfiles/3.1_1.9.2.gemfile +33 -0
- data/gemfiles/3.1_1.9.2.gemfile.lock +203 -0
- data/gemfiles/3.2.gemfile +18 -2
- data/gemfiles/3.2.gemfile.lock +32 -2
- data/gemfiles/3.2_1.9.2.gemfile +32 -0
- data/gemfiles/3.2_1.9.2.gemfile.lock +200 -0
- data/gemfiles/4.0.0.gemfile +20 -1
- data/gemfiles/4.0.0.gemfile.lock +46 -2
- data/gemfiles/4.0.1.gemfile +20 -1
- data/gemfiles/4.0.1.gemfile.lock +46 -2
- data/gemfiles/4.1.gemfile +21 -2
- data/gemfiles/4.1.gemfile.lock +47 -4
- data/lib/shoulda/matchers/action_controller.rb +0 -20
- data/lib/shoulda/matchers/action_controller/callback_matcher.rb +119 -28
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +22 -6
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +43 -10
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +40 -13
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +63 -11
- data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +34 -1
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +84 -15
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +84 -28
- data/lib/shoulda/matchers/action_controller/route_params.rb +4 -3
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +76 -13
- data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +147 -13
- data/lib/shoulda/matchers/action_controller/strong_parameters_matcher.rb +148 -2
- data/lib/shoulda/matchers/active_model.rb +0 -25
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +66 -9
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +161 -19
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +5 -5
- data/lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb +92 -13
- data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +218 -16
- data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +198 -32
- data/lib/shoulda/matchers/active_model/errors.rb +5 -2
- data/lib/shoulda/matchers/active_model/exception_message_finder.rb +1 -1
- data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +29 -8
- data/lib/shoulda/matchers/active_model/helpers.rb +20 -8
- data/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +4 -6
- data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +3 -2
- data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +52 -14
- data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +51 -13
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +53 -7
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +275 -19
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +84 -14
- data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +170 -41
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +20 -15
- data/lib/shoulda/matchers/active_model/validation_message_finder.rb +1 -2
- data/lib/shoulda/matchers/active_record.rb +1 -12
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +89 -15
- data/lib/shoulda/matchers/active_record/association_matcher.rb +726 -70
- data/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +2 -1
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +4 -5
- data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +79 -15
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +64 -15
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +21 -7
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +85 -10
- data/lib/shoulda/matchers/assertion_error.rb +7 -1
- data/lib/shoulda/matchers/doublespeak.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/double.rb +3 -1
- data/lib/shoulda/matchers/doublespeak/double_collection.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +1 -0
- data/lib/shoulda/matchers/doublespeak/object_double.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/structs.rb +2 -0
- data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/world.rb +3 -4
- data/lib/shoulda/matchers/error.rb +1 -0
- data/lib/shoulda/matchers/independent/delegate_matcher.rb +108 -20
- data/lib/shoulda/matchers/independent/delegate_matcher/stubbed_target.rb +4 -3
- data/lib/shoulda/matchers/integrations/nunit_test_case_detection.rb +3 -0
- data/lib/shoulda/matchers/rails_shim.rb +3 -2
- data/lib/shoulda/matchers/version.rb +2 -1
- data/lib/shoulda/matchers/warn.rb +1 -0
- data/script/SUPPORTED_VERSIONS +1 -0
- data/script/install_gems_in_all_appraisals +14 -0
- data/script/run_all_tests +14 -0
- data/shoulda-matchers.gemspec +0 -10
- data/spec/report_warnings.rb +7 -0
- data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +1 -1
- data/spec/shoulda/matchers/action_controller/strong_parameters_matcher_spec.rb +9 -0
- data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +0 -36
- data/spec/shoulda/matchers/active_model/validation_message_finder_spec.rb +2 -2
- data/spec/shoulda/matchers/doublespeak/double_spec.rb +1 -1
- data/spec/shoulda/matchers/doublespeak/world_spec.rb +11 -29
- data/spec/shoulda/matchers/doublespeak_spec.rb +3 -3
- data/spec/spec_helper.rb +17 -0
- data/spec/support/class_builder.rb +4 -0
- data/spec/support/test_application.rb +1 -1
- data/spec/warnings_spy.rb +64 -0
- data/spec/warnings_spy/filesystem.rb +45 -0
- data/spec/warnings_spy/partitioner.rb +29 -0
- data/spec/warnings_spy/reader.rb +64 -0
- data/spec/warnings_spy/reporter.rb +87 -0
- metadata +49 -134
@@ -0,0 +1,7 @@
|
|
1
|
+
require File.expand_path('../warnings_spy', __FILE__)
|
2
|
+
|
3
|
+
# Adapted from <http://myronmars.to/n/dev-blog/2011/08/making-your-gem-warning-free>
|
4
|
+
|
5
|
+
warnings_spy = WarningsSpy.new('shoulda-matchers')
|
6
|
+
warnings_spy.capture_warnings
|
7
|
+
warnings_spy.report_warnings_at_exit
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Shoulda::Matchers::ActionController::RouteMatcher, type: :controller do
|
3
|
+
describe 'Shoulda::Matchers::ActionController::RouteMatcher', type: :controller do
|
4
4
|
context 'given a controller with a defined glob url' do
|
5
5
|
it 'accepts glob route' do
|
6
6
|
controller = define_controller('Examples').new
|
@@ -25,6 +25,15 @@ describe Shoulda::Matchers::ActionController do
|
|
25
25
|
|
26
26
|
expect(@controller).to permit(:name, :age).for(:create)
|
27
27
|
end
|
28
|
+
|
29
|
+
it 'can be used more than once in the same test' do
|
30
|
+
controller_for_resource_with_strong_parameters(action: :create) do
|
31
|
+
params.require(:user).permit(:name)
|
32
|
+
end
|
33
|
+
|
34
|
+
expect(@controller).to permit(:name).for(:create)
|
35
|
+
expect(@controller).not_to permit(:admin).for(:create)
|
36
|
+
end
|
28
37
|
end
|
29
38
|
end
|
30
39
|
|
@@ -383,42 +383,6 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
|
|
383
383
|
end
|
384
384
|
end
|
385
385
|
|
386
|
-
context "a model with non-nullable attribute" do
|
387
|
-
context "of type" do
|
388
|
-
[:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |type|
|
389
|
-
context type do
|
390
|
-
it "does not raise an error" do
|
391
|
-
model = define_model_with_non_nullable(type)
|
392
|
-
expect { expect(model).to matcher }.not_to raise_error
|
393
|
-
end
|
394
|
-
end
|
395
|
-
end
|
396
|
-
end
|
397
|
-
|
398
|
-
context "that is a primary key" do
|
399
|
-
it "does not cause duplicate entry errors by re-using default values for primary keys" do
|
400
|
-
create_table :examples, id: false do |t|
|
401
|
-
t.string :attr
|
402
|
-
t.integer :non_nullable, primary: true
|
403
|
-
end
|
404
|
-
model_class = define_model(:example, attr: :string) do
|
405
|
-
validates_uniqueness_of :attr
|
406
|
-
end
|
407
|
-
model_1 = model_class.new
|
408
|
-
model_2 = model_class.new
|
409
|
-
expect(model_1).to matcher
|
410
|
-
expect { expect(model_2).to matcher }.not_to raise_error
|
411
|
-
end
|
412
|
-
end
|
413
|
-
|
414
|
-
def define_model_with_non_nullable(type)
|
415
|
-
define_model(:example, attr: :string, non_nullable: { type: type, options: { null: false } }) do
|
416
|
-
attr_accessible :attr, :non_nullable
|
417
|
-
validates_uniqueness_of :attr
|
418
|
-
end.new
|
419
|
-
end
|
420
|
-
end
|
421
|
-
|
422
386
|
def case_sensitive_validation_with_existing_value(attr_type)
|
423
387
|
model = define_model(:example, attr: attr_type) do
|
424
388
|
attr_accessible :attr
|
@@ -67,7 +67,7 @@ describe Shoulda::Matchers::ActiveModel::ValidationMessageFinder do
|
|
67
67
|
|
68
68
|
description = finder.messages_description
|
69
69
|
|
70
|
-
expected_messages = ['
|
70
|
+
expected_messages = ['is invalid (attribute: "attr", value: "xyz")']
|
71
71
|
expect(description).to eq "errors: #{expected_messages}"
|
72
72
|
end
|
73
73
|
|
@@ -87,7 +87,7 @@ describe Shoulda::Matchers::ActiveModel::ValidationMessageFinder do
|
|
87
87
|
end.new
|
88
88
|
finder = Shoulda::Matchers::ActiveModel::ValidationMessageFinder.new(instance, :attribute)
|
89
89
|
|
90
|
-
expected_messages = ['association.association_attribute
|
90
|
+
expected_messages = ['is invalid (attribute: "association.association_attribute")']
|
91
91
|
expect(finder.messages_description).to eq "errors: #{expected_messages}"
|
92
92
|
end
|
93
93
|
|
@@ -103,7 +103,7 @@ module Shoulda::Matchers::Doublespeak
|
|
103
103
|
|
104
104
|
describe '#call_original_method' do
|
105
105
|
it 'binds the stored method object to the class and calls it with the given args and block' do
|
106
|
-
klass = create_class
|
106
|
+
klass = create_class
|
107
107
|
instance = klass.new
|
108
108
|
actual_args = actual_block = method_called = nil
|
109
109
|
expected_args = [:one, :two, :three]
|
@@ -2,18 +2,19 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Shoulda::Matchers::Doublespeak
|
4
4
|
describe World do
|
5
|
-
describe '#
|
6
|
-
it 'calls DoubleCollection.new with the given class' do
|
7
|
-
DoubleCollection.expects(:new).with(:klass)
|
5
|
+
describe '#double_collection_for' do
|
6
|
+
it 'calls DoubleCollection.new once with the given class' do
|
7
|
+
DoubleCollection.expects(:new).with(:klass).returns(:klass).once
|
8
8
|
world = described_class.new
|
9
|
-
world.
|
9
|
+
world.double_collection_for(:klass)
|
10
|
+
world.double_collection_for(:klass)
|
10
11
|
end
|
11
12
|
|
12
|
-
it 'returns the
|
13
|
+
it 'returns the created DoubleCollection' do
|
13
14
|
double_collection = Object.new
|
14
15
|
DoubleCollection.stubs(:new).with(:klass).returns(double_collection)
|
15
16
|
world = described_class.new
|
16
|
-
expect(world.
|
17
|
+
expect(world.double_collection_for(:klass)).to be double_collection
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
@@ -40,9 +41,9 @@ module Shoulda::Matchers::Doublespeak
|
|
40
41
|
DoubleCollection.stubs(:new).
|
41
42
|
with(:klass3).
|
42
43
|
returns(double_collections[2])
|
43
|
-
world.
|
44
|
-
world.
|
45
|
-
world.
|
44
|
+
world.double_collection_for(:klass1)
|
45
|
+
world.double_collection_for(:klass2)
|
46
|
+
world.double_collection_for(:klass3)
|
46
47
|
|
47
48
|
world.with_doubles_activated { block_called = true }
|
48
49
|
|
@@ -57,32 +58,13 @@ module Shoulda::Matchers::Doublespeak
|
|
57
58
|
world = described_class.new
|
58
59
|
|
59
60
|
DoubleCollection.stubs(:new).returns(double_collection)
|
60
|
-
world.
|
61
|
+
world.double_collection_for(:klass)
|
61
62
|
|
62
63
|
begin
|
63
64
|
world.with_doubles_activated { raise 'error' }
|
64
65
|
rescue RuntimeError
|
65
66
|
end
|
66
67
|
end
|
67
|
-
|
68
|
-
it 'does not allow multiple DoubleCollections to be registered that represent the same class' do
|
69
|
-
double_collections = [stub, stub]
|
70
|
-
sequence = sequence('with_doubles_activated')
|
71
|
-
double_collections[0].expects(:activate).never
|
72
|
-
double_collections[0].expects(:deactivate).never
|
73
|
-
double_collections[1].expects(:activate).in_sequence(sequence)
|
74
|
-
double_collections[1].expects(:deactivate).in_sequence(sequence)
|
75
|
-
|
76
|
-
world = described_class.new
|
77
|
-
|
78
|
-
DoubleCollection.stubs(:new).
|
79
|
-
returns(double_collections[0]).then.
|
80
|
-
returns(double_collections[1])
|
81
|
-
world.register_double_collection(:klass1)
|
82
|
-
world.register_double_collection(:klass1)
|
83
|
-
|
84
|
-
world.with_doubles_activated { }
|
85
|
-
end
|
86
68
|
end
|
87
69
|
end
|
88
70
|
end
|
@@ -2,10 +2,10 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Shoulda::Matchers
|
4
4
|
describe Doublespeak do
|
5
|
-
describe '.
|
5
|
+
describe '.double_collection_for' do
|
6
6
|
it 'delegates to its world' do
|
7
|
-
Doublespeak.world.expects(:
|
8
|
-
described_class.
|
7
|
+
Doublespeak.world.expects(:double_collection_for).with(:klass)
|
8
|
+
described_class.double_collection_for(:klass)
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,24 @@
|
|
1
1
|
require File.expand_path('../support/test_application', __FILE__)
|
2
2
|
|
3
|
+
def monkey_patch_minitest_to_do_nothing
|
4
|
+
# Rails 3.1's test_help file requires Turn, which loads Minitest in autorun
|
5
|
+
# mode. This means that Minitest tests will run after these RSpec tests are
|
6
|
+
# finished running. This will break on CI since we pass --color to the `rspec`
|
7
|
+
# command.
|
8
|
+
|
9
|
+
if defined?(MiniTest)
|
10
|
+
MiniTest::Unit.class_eval do
|
11
|
+
def run(*); end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
3
16
|
$test_app = TestApplication.new
|
4
17
|
$test_app.create
|
5
18
|
$test_app.load
|
6
19
|
|
20
|
+
monkey_patch_minitest_to_do_nothing
|
21
|
+
|
7
22
|
ENV['BUNDLE_GEMFILE'] ||= app.gemfile_path
|
8
23
|
ENV['RAILS_ENV'] = 'test'
|
9
24
|
|
@@ -24,3 +39,5 @@ RSpec.configure do |config|
|
|
24
39
|
config.include Shoulda::Matchers::ActionController,
|
25
40
|
example_group: { file_path: /action_controller/ }
|
26
41
|
end
|
42
|
+
|
43
|
+
$VERBOSE = true
|
@@ -10,6 +10,10 @@ module ClassBuilder
|
|
10
10
|
def define_class(class_name, base = Object, &block)
|
11
11
|
class_name = class_name.to_s.camelize
|
12
12
|
|
13
|
+
if Object.const_defined?(class_name)
|
14
|
+
Object.__send__(:remove_const, class_name)
|
15
|
+
end
|
16
|
+
|
13
17
|
# FIXME: ActionMailer 3.2 calls `name.underscore` immediately upon
|
14
18
|
# subclassing. Class.new.name == nil. So, Class.new(ActionMailer::Base)
|
15
19
|
# errors out since it's trying to do `nil.underscore`. This is very ugly but
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
require File.expand_path('../warnings_spy/filesystem', __FILE__)
|
4
|
+
require File.expand_path('../warnings_spy/reader', __FILE__)
|
5
|
+
require File.expand_path('../warnings_spy/partitioner', __FILE__)
|
6
|
+
require File.expand_path('../warnings_spy/reporter', __FILE__)
|
7
|
+
|
8
|
+
class WarningsSpy
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
def initialize(project_name)
|
12
|
+
filesystem = Filesystem.new
|
13
|
+
@warnings_file = filesystem.warnings_file
|
14
|
+
@reader = Reader.new(filesystem)
|
15
|
+
@partitioner = Partitioner.new(reader, filesystem)
|
16
|
+
@reporter = Reporter.new(partitioner, filesystem, project_name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def capture_warnings
|
20
|
+
$stderr.reopen(warnings_file.path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def report_warnings_at_exit
|
24
|
+
at_exit do
|
25
|
+
printing_exceptions do
|
26
|
+
report_and_exit
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
attr_reader :warnings_file, :reader, :partitioner, :reporter
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def_delegators :partitioner, :relevant_warning_groups,
|
38
|
+
:irrelevant_warning_groups
|
39
|
+
|
40
|
+
def report_and_exit
|
41
|
+
reader.read
|
42
|
+
partitioner.partition
|
43
|
+
reporter.report
|
44
|
+
#fail_build_if_there_are_any_warnings
|
45
|
+
end
|
46
|
+
|
47
|
+
def fail_build_if_there_are_any_warnings
|
48
|
+
if relevant_warning_groups.any?
|
49
|
+
exit(1)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def printing_exceptions
|
54
|
+
begin
|
55
|
+
yield
|
56
|
+
rescue => error
|
57
|
+
puts "\n--- ERROR IN AT_EXIT --------------------------------"
|
58
|
+
puts "#{error.class}: #{error.message}"
|
59
|
+
puts error.backtrace.join("\n")
|
60
|
+
puts "-----------------------------------------------------"
|
61
|
+
raise error
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
class WarningsSpy
|
4
|
+
class Filesystem
|
5
|
+
PROJECT_DIR = File.expand_path('../../..', __FILE__)
|
6
|
+
TEMP_DIR = File.join(PROJECT_DIR, 'tmp')
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@files_by_name = Hash.new do |hash, name|
|
10
|
+
FileUtils.mkdir_p(TEMP_DIR)
|
11
|
+
hash[name] = file_for(name)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def warnings_file
|
16
|
+
files_by_name['all_warnings']
|
17
|
+
end
|
18
|
+
|
19
|
+
def irrelevant_warnings_file
|
20
|
+
files_by_name['irrelevant_warnings']
|
21
|
+
end
|
22
|
+
|
23
|
+
def relevant_warnings_file
|
24
|
+
files_by_name['relevant_warnings']
|
25
|
+
end
|
26
|
+
|
27
|
+
def project_dir
|
28
|
+
PROJECT_DIR
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
attr_reader :files_by_name
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def path_for(name)
|
38
|
+
File.join(TEMP_DIR, "#{name}.txt")
|
39
|
+
end
|
40
|
+
|
41
|
+
def file_for(name)
|
42
|
+
File.open(path_for(name), 'w+')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
class WarningsSpy
|
4
|
+
class Partitioner
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
attr_reader :relevant_warning_groups, :irrelevant_warning_groups
|
8
|
+
|
9
|
+
def initialize(reader, filesystem)
|
10
|
+
@reader = reader
|
11
|
+
@search_text = filesystem.project_dir
|
12
|
+
end
|
13
|
+
|
14
|
+
def partition
|
15
|
+
@relevant_warning_groups, @irrelevant_warning_groups =
|
16
|
+
warning_groups.partition do |group|
|
17
|
+
group.any? { |line| line.include?(search_text) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
attr_reader :reader, :search_text
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def_delegators :reader, :warning_groups
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class WarningsSpy
|
2
|
+
class Reader
|
3
|
+
attr_reader :warning_groups
|
4
|
+
|
5
|
+
def initialize(filesystem)
|
6
|
+
@warnings_file = filesystem.warnings_file
|
7
|
+
|
8
|
+
@recording = false
|
9
|
+
@current_group = []
|
10
|
+
@warning_groups = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def read
|
14
|
+
warnings_file.rewind
|
15
|
+
|
16
|
+
warnings_file.each_line do |line|
|
17
|
+
process_line(line)
|
18
|
+
end
|
19
|
+
|
20
|
+
add_group(current_group)
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
attr_reader :warnings_file, :current_group
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def process_line(line)
|
30
|
+
if backtrace_line?(line) && recording?
|
31
|
+
current_group << line
|
32
|
+
else
|
33
|
+
unless current_group.empty?
|
34
|
+
add_group(current_group)
|
35
|
+
current_group.clear
|
36
|
+
end
|
37
|
+
|
38
|
+
current_group << line
|
39
|
+
|
40
|
+
@recording = true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_group(group)
|
45
|
+
unless group_already_added?(group)
|
46
|
+
warning_groups << group
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def group_already_added?(group_to_be_added)
|
51
|
+
warning_groups.any? do |group|
|
52
|
+
group == group_to_be_added
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def backtrace_line?(line)
|
57
|
+
line =~ /^\s+/
|
58
|
+
end
|
59
|
+
|
60
|
+
def recording?
|
61
|
+
@recording
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|