ensure_it 0.1.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.
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