ensure_it 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +7 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +332 -0
  9. data/Rakefile +11 -0
  10. data/ensure_it.gemspec +39 -0
  11. data/lib/ensure_it/config.rb +23 -0
  12. data/lib/ensure_it/ensure_array.rb +67 -0
  13. data/lib/ensure_it/ensure_class.rb +30 -0
  14. data/lib/ensure_it/ensure_float.rb +48 -0
  15. data/lib/ensure_it/ensure_hash.rb +22 -0
  16. data/lib/ensure_it/ensure_instance_of.rb +27 -0
  17. data/lib/ensure_it/ensure_integer.rb +89 -0
  18. data/lib/ensure_it/ensure_string.rb +43 -0
  19. data/lib/ensure_it/ensure_symbol.rb +26 -0
  20. data/lib/ensure_it/errors.rb +173 -0
  21. data/lib/ensure_it/patch.rb +17 -0
  22. data/lib/ensure_it/version.rb +3 -0
  23. data/lib/ensure_it.rb +18 -0
  24. data/lib/ensure_it_refines.rb +8 -0
  25. data/spec/integration/refines_spec.rb +37 -0
  26. data/spec/lib/config_spec.rb +50 -0
  27. data/spec/lib/ensure_array_spec.rb +75 -0
  28. data/spec/lib/ensure_class_spec.rb +54 -0
  29. data/spec/lib/ensure_float_spec.rb +65 -0
  30. data/spec/lib/ensure_hash_spec.rb +45 -0
  31. data/spec/lib/ensure_instance_of_spec.rb +49 -0
  32. data/spec/lib/ensure_integer_spec.rb +89 -0
  33. data/spec/lib/ensure_string_spec.rb +53 -0
  34. data/spec/lib/ensure_symbol_spec.rb +39 -0
  35. data/spec/lib/errors_spec.rb +124 -0
  36. data/spec/lib/patch_spec.rb +31 -0
  37. data/spec/spec_helper.rb +19 -0
  38. data/spec/support/example_groups/ensure_it_example_group.rb +66 -0
  39. data/spec/support/matchers/warn_matcher.rb +30 -0
  40. data/spec/support/shared_examples/unmet_objects.rb +60 -0
  41. metadata +177 -0
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ class Tester
4
+ using EnsureIt if ENSURE_IT_REFINES
5
+
6
+ def ensure_hash(*args)
7
+ obj.ensure_hash(*args)
8
+ end
9
+
10
+ def ensure_hash!(*args)
11
+ obj.ensure_hash!(*args)
12
+ end
13
+ end
14
+
15
+ describe EnsureIt do
16
+ shared_examples 'hash parser' do
17
+ it 'and returns self for array' do
18
+ obj = {some: 0, 'key' => 1}
19
+ expect(call_for(obj)).to eq obj
20
+ end
21
+
22
+ it 'symbolizes keys with symbolize_keys option' do
23
+ obj = {some: 0, 'key' => 1, Object => 'strange'}
24
+ expect(call_for(obj, symbolize_keys: true)).to eq(some: 0, key: 1)
25
+ end
26
+ end
27
+
28
+ describe '#ensure_hash' do
29
+ it_behaves_like 'hash parser'
30
+ it_behaves_like 'empty hash creator for unmet objects', except: Hash
31
+
32
+ it 'and returns nil with wrong: nil option' do
33
+ expect(call_for(true, wrong: nil)).to be_nil
34
+ expect(call_for(true, wrong: 1)).to eq 1
35
+ end
36
+ end
37
+
38
+ describe '#ensure_hash!' do
39
+ it_behaves_like 'hash parser'
40
+ it_behaves_like(
41
+ 'banger for unmet objects', except: Hash,
42
+ message: /should be a Hash/
43
+ )
44
+ end
45
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ class Tester
4
+ using EnsureIt if ENSURE_IT_REFINES
5
+
6
+ def ensure_instance_of(*args)
7
+ obj.ensure_instance_of(*args)
8
+ end
9
+
10
+ def ensure_instance_of!(*args)
11
+ obj.ensure_instance_of!(*args)
12
+ end
13
+ end
14
+
15
+ describe EnsureIt do
16
+ shared_examples 'instance selector' do
17
+ it 'and returns self for right instances' do
18
+ expect(call_for(:test, Symbol)).to eq :test
19
+ expect(call_for('test', String)).to eq 'test'
20
+ end
21
+
22
+ it 'and raises ArgumentError for wrong class' do
23
+ expect { call_for(:test, 1) }.to raise_error ArgumentError
24
+ end
25
+ end
26
+
27
+ describe '#ensure_instance_of' do
28
+ it_behaves_like 'instance selector'
29
+
30
+ it 'returns nil for wrong instances' do
31
+ expect(call_for(:test, String)).to be_nil
32
+ expect(call_for('test', Symbol)).to be_nil
33
+ end
34
+
35
+ it 'returns wrong option for wrong instances' do
36
+ expect(call_for(:test, String, wrong: 1)).to eq 1
37
+ end
38
+ end
39
+
40
+ describe '#ensure_instance_of!' do
41
+ it_behaves_like 'instance selector'
42
+
43
+ it 'raises on wrong instances and classes' do
44
+ expect {
45
+ call_for(:test, String)
46
+ }.to raise_error EnsureIt::Error, /should be an instance of .* class/
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ class Tester
4
+ using EnsureIt if ENSURE_IT_REFINES
5
+
6
+ def ensure_integer(*args)
7
+ obj.ensure_integer(*args)
8
+ end
9
+
10
+ def ensure_integer!(*args)
11
+ obj.ensure_integer!(*args)
12
+ end
13
+ end
14
+
15
+ describe EnsureIt do
16
+ shared_examples 'numerizer' do
17
+ it 'and returns self for Fixnum' do
18
+ obj = 1000
19
+ expect(call_for(obj)).to eq obj
20
+ end
21
+
22
+ it 'and returns self for Bignum' do
23
+ obj = BIGNUM
24
+ expect(call_for(obj)).to eq obj
25
+ end
26
+
27
+ it 'and converts decimal strings' do
28
+ expect(call_for('-100')).to eq(-100)
29
+ end
30
+
31
+ it 'and converts decimal strings with delimiter' do
32
+ expect(call_for('1_200')).to eq(1200)
33
+ end
34
+
35
+ it 'and converts hex strings' do
36
+ expect(call_for('0x0a')).to eq(10)
37
+ end
38
+
39
+ it 'and converts binary strings' do
40
+ expect(call_for('0b100')).to eq(4)
41
+ end
42
+
43
+ it 'and converts octal strings as decimal' do
44
+ expect(call_for('010')).to eq(10)
45
+ end
46
+
47
+ it 'and converts octal strings as octal with octal: true' do
48
+ expect(call_for('010', octal: true)).to eq(8)
49
+ end
50
+
51
+ it 'and rounds floats' do
52
+ expect(call_for(10.1)).to eq(10)
53
+ expect(call_for(10.5)).to eq(11)
54
+ end
55
+
56
+ it 'and converts rationales' do
57
+ expect(call_for(Rational(5, 2).to_r)).to eq(3)
58
+ end
59
+
60
+ it 'and converts boolean with :boolean option' do
61
+ expect(call_for(true, boolean: true)).to eq 1
62
+ expect(call_for(false, boolean: true)).to eq 0
63
+ end
64
+
65
+ it 'and converts boolean with numeric :boolean option' do
66
+ expect(call_for(true, boolean: 100)).to eq 100
67
+ expect(call_for(false, boolean: 100)).to eq 0
68
+ end
69
+ end
70
+
71
+ describe '#ensure_integer' do
72
+ it_behaves_like 'numerizer'
73
+ it_behaves_like(
74
+ 'niller for unmet objects',
75
+ '123test', :test123, :'100',
76
+ except: [String, Symbol, Integer, Float, Rational]
77
+ )
78
+ end
79
+
80
+ describe '#ensure_integer!' do
81
+ it_behaves_like 'numerizer'
82
+ it_behaves_like(
83
+ 'banger for unmet objects',
84
+ '123test', :test123, :'100',
85
+ except: [String, Symbol, Integer, Float, Rational],
86
+ message: /should be an integer or be able to convert to it/
87
+ )
88
+ end
89
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ class Tester
4
+ using EnsureIt if ENSURE_IT_REFINES
5
+
6
+ def ensure_string(*args)
7
+ obj.ensure_string(*args)
8
+ end
9
+
10
+ def ensure_string!(*args)
11
+ obj.ensure_string!(*args)
12
+ end
13
+ end
14
+
15
+ describe EnsureIt do
16
+ shared_examples 'stringifier' do
17
+ it 'and returns self for string' do
18
+ obj = 'test'
19
+ expect(call_for(obj)).to eq obj
20
+ end
21
+
22
+ it 'and converts symbols to string' do
23
+ expect(call_for(:test)).to eq 'test'
24
+ end
25
+
26
+ it 'and converts numbers to string with :numbers option' do
27
+ expect(call_for(100, numbers: true)).to eq '100'
28
+ expect(call_for(0.5, numbers: true)).to eq '0.5'
29
+ expect(call_for(Rational(2, 3), numbers: true)).to eq '2/3'
30
+ end
31
+ end
32
+
33
+ describe '#ensure_string' do
34
+ it_behaves_like 'stringifier'
35
+ it_behaves_like 'niller for unmet objects', except: [String, Symbol]
36
+ end
37
+
38
+ describe '#ensure_string!' do
39
+ it_behaves_like 'stringifier'
40
+ it_behaves_like(
41
+ 'banger for unmet objects',
42
+ except: [String, Symbol],
43
+ message: /should be a String or a Symbol/
44
+ )
45
+
46
+ it 'raises correct error message with :numbers option' do
47
+ expect { call_for(nil, numbers: true) }.to raise_error(
48
+ EnsureIt::Error,
49
+ /should be a String, Symbol, Numeric or Rational/
50
+ )
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ class Tester
4
+ using EnsureIt if ENSURE_IT_REFINES
5
+
6
+ def ensure_symbol(*args)
7
+ obj.ensure_symbol(*args)
8
+ end
9
+
10
+ def ensure_symbol!(*args)
11
+ obj.ensure_symbol!(*args)
12
+ end
13
+ end
14
+
15
+ describe EnsureIt do
16
+ shared_examples 'symbolizer' do
17
+ it 'and returns self for symbol' do
18
+ expect(call_for(:test)).to eq :test
19
+ end
20
+
21
+ it 'and converts string to symbol' do
22
+ expect(call_for('test')).to eq :test
23
+ end
24
+ end
25
+
26
+ describe '#ensure_symbol' do
27
+ it_behaves_like 'symbolizer'
28
+ it_behaves_like 'niller for unmet objects', except: [String, Symbol]
29
+ end
30
+
31
+ describe '#ensure_symbol!' do
32
+ it_behaves_like 'symbolizer'
33
+ it_behaves_like(
34
+ 'banger for unmet objects',
35
+ except: [String, Symbol],
36
+ message: /should be a Symbol or a String/
37
+ )
38
+ end
39
+ end
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ describe EnsureIt::Error do
4
+ it 'is StandardError' do
5
+ expect(described_class < StandardError).to be_true
6
+ end
7
+ end
8
+
9
+ describe EnsureIt do
10
+ describe '.raise_error' do
11
+ after { EnsureIt::Config.instance_variable_set(:@errors, nil) }
12
+
13
+ it 'raises EnsureIt::Error by default' do
14
+ expect {
15
+ call_error(:test_method)
16
+ }.to raise_error EnsureIt::Error
17
+ end
18
+
19
+ it 'raisesspecified error and message' do
20
+ expect {
21
+ call_error(:test_method, error: ArgumentError, message: 'test')
22
+ }.to raise_error ArgumentError, 'test'
23
+ end
24
+
25
+ it 'raises error with callers backtrace' do
26
+ backtrace = nil
27
+ begin
28
+ call_error(:test_method)
29
+ rescue EnsureIt::Error => e
30
+ backtrace = e.backtrace
31
+ end
32
+ expect(backtrace.first).to match(/\A#{__FILE__}:#{__LINE__ - 4}:/)
33
+ end
34
+
35
+ context 'standard errors' do
36
+ before { EnsureIt.config.errors :standard }
37
+ end
38
+
39
+ context 'smart errors' do
40
+ before { EnsureIt.config.errors :smart }
41
+
42
+ def test_unknown_caller
43
+ local = ''
44
+ local
45
+ .to_s; call_error(:to_s, message: '#{subject}')
46
+ end
47
+
48
+ def test_local_caller
49
+ local = ''
50
+ local.to_s; call_error(:to_s, message: '#{subject}')
51
+ end
52
+
53
+ def test_instance_caller
54
+ @instance = ''
55
+ @instance.to_s; call_error(:to_s, message: '#{subject}')
56
+ end
57
+
58
+ def test_class_caller
59
+ backup = $VERBOSE
60
+ $VERBOSE = nil
61
+ @@class = ''
62
+ @@class.to_s; call_error(:to_s, message: '#{subject}')
63
+ ensure
64
+ $VERBOSE = backup
65
+ end
66
+
67
+ def test_method_1_caller
68
+ local = ''
69
+ local.to_sym.to_s; call_error(:to_s, message: '#{subject}')
70
+ end
71
+
72
+ def test_method_2_caller
73
+ local = ''
74
+ local.to_sym().to_s; call_error(:to_s, message: '#{subject}')
75
+ end
76
+
77
+ def test_argument_1_caller(arg_1)
78
+ arg_1.to_s; call_error(:to_s, message: '#{subject}')
79
+ end
80
+
81
+ def test_argument_2_caller(*args)
82
+ args.to_s; call_error(:to_s, message: '#{subject}')
83
+ end
84
+
85
+ def test_argument_3_caller(arg_1 = 'test')
86
+ arg_1.to_s; call_error(:to_s, message: '#{subject}')
87
+ end
88
+
89
+ def test_argument_4_caller(arg_1: 'test')
90
+ arg_1.to_s; call_error(:to_s, message: '#{subject}')
91
+ end
92
+
93
+ def test_argument_5_caller(**opts)
94
+ opts.to_s; call_error(:to_s, message: '#{subject}')
95
+ end
96
+
97
+ def test_argument_6_caller(&block)
98
+ block.to_s; call_error(:to_s, message: '#{subject}')
99
+ end
100
+
101
+ {
102
+ unknown: %q{subject of 'to_s' method inside 'test_unknown_caller' method},
103
+ local: %q{local variable 'local' inside 'test_local_caller' method},
104
+ instance: %q{instance variable '@instance' inside 'test_instance_caller' method},
105
+ class: %q{class variable '@@class' inside 'test_class_caller' method},
106
+ method_1: %q{return value of 'to_sym' method inside 'test_method_1_caller' method},
107
+ method_2: %q{return value of method inside 'test_method_2_caller' method},
108
+ argument_1: %q{argument 'arg_1' of 'test_argument_1_caller' method},
109
+ argument_2: %q{argument '*args' of 'test_argument_2_caller' method},
110
+ argument_3: %q{optional argument 'arg_1' of 'test_argument_3_caller' method},
111
+ argument_4: %q{key argument 'arg_1' of 'test_argument_4_caller' method},
112
+ argument_5: %q{key argument '**opts' of 'test_argument_5_caller' method},
113
+ argument_6: %q{block argument '&block' of 'test_argument_6_caller' method},
114
+ }.each do |var, message|
115
+ it "finds #{var} name" do
116
+ m = method("test_#{var}_caller")
117
+ args = [true] * (m.arity < 0 ? -m.arity - 1 : m.arity)
118
+ error = get_error { m.call(*args) }
119
+ expect(error.message).to eq message
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ class PatchTestClass; end
4
+ module PatchTestWrapper; end
5
+
6
+ describe EnsureIt do
7
+ describe '::patch' do
8
+ it 'is private' do
9
+ expect { EnsureIt.patch(PatchTestClass) {} }.to raise_error NoMethodError
10
+ end
11
+
12
+ it 'includes methods to object' do
13
+ expect { PatchTestWrapper.obj.test_method }.to raise_error NoMethodError
14
+ EnsureIt.send(:patch, PatchTestClass, &proc do
15
+ def test_method
16
+ 'test result'
17
+ end
18
+ end)
19
+ result =
20
+ if ENSURE_IT_REFINES
21
+ PatchTestWrapper.module_eval do
22
+ using EnsureIt
23
+ PatchTestClass.new.test_method
24
+ end
25
+ else
26
+ PatchTestClass.new.test_method
27
+ end
28
+ expect(result).to eq 'test result'
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ #require 'coveralls'
2
+ #Coveralls.wear!
3
+
4
+ if ENV['USE_REFINES'] == 'true'
5
+ require 'ensure_it_refines'
6
+ else
7
+ require 'ensure_it'
8
+ end
9
+
10
+ Dir[File.join(File.dirname(__FILE__), 'support', '**', '*.rb')].each do |file|
11
+ require file
12
+ end
13
+
14
+ RSpec.configure do |config|
15
+ config.treat_symbols_as_metadata_keys_with_true_values = true
16
+ config.run_all_when_everything_filtered = true
17
+ config.filter_run :focus
18
+ config.order = 'random'
19
+ end
@@ -0,0 +1,66 @@
1
+ #
2
+ # Helpers for ensure_it testing
3
+ #
4
+ # @author Alexey Ovchinnikov <alexiss@cybernetlab.ru>
5
+ #
6
+
7
+ class Tester
8
+ attr_reader :obj
9
+
10
+ def initialize(obj)
11
+ @obj = obj
12
+ end
13
+ end
14
+
15
+ module EnsureItExampleGroup
16
+ def self.fake_method; end
17
+
18
+ def self.included(base)
19
+ base.instance_eval do
20
+ metadata[:type] = :ensure_it
21
+ end
22
+ end
23
+
24
+ def general_objects(&block)
25
+ enum = GENERAL_OBJECTS.each
26
+ enum.define_singleton_method :except do |*classes|
27
+ classes = classes.flatten.select { |x| x.is_a?(Class) }
28
+ reject { |obj| classes.any? { |c| obj.is_a?(c) } }
29
+ end
30
+ block_given? ? enum.each(&block) : enum
31
+ end
32
+
33
+ def described_method
34
+ group = example.metadata[:example_group]
35
+ while group do
36
+ break if group[:description][0] == '#'
37
+ group = group[:example_group]
38
+ end
39
+ if group.nil?
40
+ raise RuntimeError, 'No description, containing method name founded'
41
+ end
42
+ group[:description][1..-1].to_sym
43
+ end
44
+
45
+ def call_for(obj, *args)
46
+ Tester.new(obj).send(described_method, *args)
47
+ end
48
+
49
+ def call_error(method_name, **opts)
50
+ EnsureIt.raise_error(method_name, **opts)
51
+ end
52
+
53
+ def get_error
54
+ yield
55
+ rescue EnsureIt::Error => e
56
+ e
57
+ end
58
+
59
+ RSpec.configure do |config|
60
+ config.include(
61
+ self,
62
+ type: :ensure_it,
63
+ example_group: { file_path: /spec\/lib/ }
64
+ )
65
+ end
66
+ end
@@ -0,0 +1,30 @@
1
+ RSpec::Matchers.define :warn do |message|
2
+ match do |block|
3
+ output = capture_stderr(&block)
4
+ message.is_a?(Regexp) ? message.match(output) : output.include?(message)
5
+ end
6
+
7
+ description do
8
+ "warn with message \"#{message}\""
9
+ end
10
+
11
+ failure_message_for_should do
12
+ "expected to #{description}"
13
+ end
14
+
15
+ failure_message_for_should_not do
16
+ "expected to not #{description}"
17
+ end
18
+
19
+ # Fake STDERR and return a string written to it.
20
+ def capture_stderr(&block)
21
+ original_stderr = $stderr
22
+ $stderr = fake = StringIO.new
23
+ begin
24
+ yield
25
+ ensure
26
+ $stderr = original_stderr
27
+ end
28
+ fake.string
29
+ end
30
+ end
@@ -0,0 +1,60 @@
1
+ #using EnsureIt if ENSURE_IT_REFINES
2
+
3
+ def fake_method; end
4
+
5
+ FIXNUM_MAX = (2 ** (0.size * 8 - 2) - 1)
6
+ BIGNUM = FIXNUM_MAX + 100
7
+ FIXNUM = FIXNUM_MAX - 100
8
+ GENERAL_OBJECTS = [
9
+ [], {}, FIXNUM, BIGNUM, 0.1, true, false, nil, 0..5,
10
+ '2/3'.to_r, /regexp/, 'string', :symbol,
11
+ ->{}, proc {}, method(:fake_method),
12
+ Object.new, Class.new, Module.new, Struct.new(:field), Time.new
13
+ ]
14
+
15
+ def compose_objects(add, except)
16
+ except = [except] unless except.is_a?(Array)
17
+ add = [add] unless add.is_a?(Array)
18
+ except = except.flatten.select { |x| x.is_a?(Class) }
19
+ objects = GENERAL_OBJECTS.reject { |obj| except.any? { |c| obj.is_a?(c) } }
20
+ objects.concat(add)
21
+ end
22
+
23
+ shared_examples 'niller for unmet objects' do |*add, except: []|
24
+ it 'returns nil' do
25
+ expect(
26
+ compose_objects(add, except).map { |x| call_for(x) }.compact
27
+ ).to be_empty
28
+ end
29
+ end
30
+
31
+ shared_examples 'empty array creator for unmet objects' do |*add, except: []|
32
+ it 'returns empty array' do
33
+ compose_objects(add, except).each do |obj|
34
+ expect(call_for(obj)).to eq []
35
+ end
36
+ end
37
+ end
38
+
39
+ shared_examples 'empty hash creator for unmet objects' do |*add, except: []|
40
+ it 'returns empty array' do
41
+ compose_objects(add, except).each do |obj|
42
+ expect(call_for(obj)).to eq({})
43
+ end
44
+ end
45
+ end
46
+
47
+ shared_examples 'banger for unmet objects' do |*add, except: [], **opts|
48
+ it 'raises error' do
49
+ objects = compose_objects(add, except)
50
+ expect(EnsureIt).to receive(:raise_error)
51
+ .exactly(objects.size).times.and_call_original
52
+ err = [opts[:error] || EnsureIt::Error]
53
+ err << opts[:message] if opts.key?(:message)
54
+ objects.each do |obj|
55
+ expect {
56
+ call_for(obj)
57
+ }.to raise_error(*err)
58
+ end
59
+ end
60
+ end