haveapi 0.4.2 → 0.5.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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +11 -0
  3. data/Rakefile +1 -0
  4. data/haveapi.gemspec +1 -1
  5. data/lib/haveapi/authentication/chain.rb +4 -0
  6. data/lib/haveapi/hooks.rb +68 -11
  7. data/lib/haveapi/model_adapters/active_record.rb +1 -1
  8. data/lib/haveapi/{params/param.rb → parameters/typed.rb} +4 -1
  9. data/lib/haveapi/params.rb +2 -2
  10. data/lib/haveapi/spec/api_builder.rb +75 -0
  11. data/lib/haveapi/spec/api_response.rb +41 -0
  12. data/lib/haveapi/spec/helpers.rb +5 -99
  13. data/lib/haveapi/spec/mock_action.rb +32 -0
  14. data/lib/haveapi/spec/spec_methods.rb +121 -0
  15. data/lib/haveapi/version.rb +1 -1
  16. data/lib/haveapi/views/main_layout.erb +3 -1
  17. data/lib/haveapi.rb +1 -1
  18. data/spec/action/dsl_spec.rb +199 -0
  19. data/spec/authorization_spec.rb +113 -0
  20. data/spec/common_spec.rb +47 -0
  21. data/spec/documentation_spec.rb +29 -0
  22. data/spec/envelope_spec.rb +33 -0
  23. data/spec/hooks_spec.rb +146 -0
  24. data/spec/parameters/typed_spec.rb +93 -0
  25. data/spec/params_spec.rb +190 -0
  26. data/spec/resource_spec.rb +63 -0
  27. data/spec/spec_helper.rb +21 -0
  28. data/spec/validators/acceptance_spec.rb +29 -0
  29. data/spec/validators/confirmation_spec.rb +46 -0
  30. data/spec/validators/custom_spec.rb +6 -0
  31. data/spec/validators/exclusion_spec.rb +32 -0
  32. data/spec/validators/format_spec.rb +54 -0
  33. data/spec/validators/inclusion_spec.rb +43 -0
  34. data/spec/validators/length_spec.rb +45 -0
  35. data/spec/validators/numericality_spec.rb +70 -0
  36. data/spec/validators/presence_spec.rb +47 -0
  37. metadata +27 -4
  38. /data/lib/haveapi/{params → parameters}/resource.rb +0 -0
@@ -0,0 +1,190 @@
1
+ describe HaveAPI::Params do
2
+ class MyResource < HaveAPI::Resource
3
+ params(:all) do
4
+ string :res_param1
5
+ string :res_param2
6
+ end
7
+
8
+ class Index < HaveAPI::Actions::Default::Index
9
+
10
+ end
11
+
12
+ class Show < HaveAPI::Actions::Default::Show
13
+ output do
14
+ string :not_label
15
+ end
16
+ end
17
+
18
+ class Create < HaveAPI::Actions::Default::Create
19
+
20
+ end
21
+ end
22
+
23
+ it 'executes all blocks' do
24
+ p = HaveAPI::Params.new(:input, MyResource::Index)
25
+ p.add_block Proc.new { string :param1 }
26
+ p.add_block Proc.new { string :param2 }
27
+ p.add_block Proc.new { string :param3 }
28
+ p.exec
29
+ expect(p.params.map { |p| p.name }).to contain_exactly(*%i(param1 param2 param3))
30
+ end
31
+
32
+ it 'returns deduced singular namespace' do
33
+ p = HaveAPI::Params.new(:input, MyResource::Index)
34
+ expect(p.namespace).to eq(:my_resource)
35
+ end
36
+
37
+ it 'returns deduced plural namespace' do
38
+ p = HaveAPI::Params.new(:input, MyResource::Index)
39
+ p.layout = :object_list
40
+ expect(p.namespace).to eq(:my_resources)
41
+ end
42
+
43
+ it 'returns set namespace' do
44
+ p = HaveAPI::Params.new(:input, MyResource::Index)
45
+ p.namespace = :custom_ns
46
+ expect(p.namespace).to eq(:custom_ns)
47
+ end
48
+
49
+ it 'uses params from parent resource' do
50
+ p = HaveAPI::Params.new(:input, MyResource::Index)
51
+ p.add_block Proc.new { use :all }
52
+ p.exec
53
+ expect(p.params.map { |p| p.name }).to contain_exactly(*%i(res_param1 res_param2))
54
+ end
55
+
56
+ it 'has param requires' do
57
+ p = HaveAPI::Params.new(:input, MyResource::Index)
58
+ p.add_block Proc.new { requires :p_required }
59
+ p.exec
60
+ expect(p.params.first.required?).to be true
61
+ end
62
+
63
+ it 'has param optional' do
64
+ p = HaveAPI::Params.new(:input, MyResource::Index)
65
+ p.add_block Proc.new { optional :p_optional }
66
+ p.exec
67
+ expect(p.params.first.required?).to be false
68
+ end
69
+
70
+ it 'has param string' do
71
+ p = HaveAPI::Params.new(:input, MyResource::Index)
72
+ p.add_block Proc.new { string :p_string }
73
+ p.exec
74
+ expect(p.params.first.type).to eq(String)
75
+ end
76
+
77
+ it 'has param text' do
78
+ p = HaveAPI::Params.new(:input, MyResource::Index)
79
+ p.add_block Proc.new { text :p_text }
80
+ p.exec
81
+ expect(p.params.first.type).to eq(Text)
82
+ end
83
+
84
+ %i(id integer foreign_key).each do |type|
85
+ it "has param #{type}" do
86
+ p = HaveAPI::Params.new(:input, MyResource::Index)
87
+ p.add_block Proc.new { send(type, :"p_#{type}") }
88
+ p.exec
89
+ expect(p.params.first.type).to eq(Integer)
90
+ end
91
+ end
92
+
93
+ it 'has param float' do
94
+ p = HaveAPI::Params.new(:input, MyResource::Index)
95
+ p.add_block Proc.new { float :p_float }
96
+ p.exec
97
+ expect(p.params.first.type).to eq(Float)
98
+ end
99
+
100
+ it 'has param bool' do
101
+ p = HaveAPI::Params.new(:input, MyResource::Index)
102
+ p.add_block Proc.new { bool :p_bool }
103
+ p.exec
104
+ expect(p.params.first.type).to eq(Boolean)
105
+ end
106
+
107
+ it 'has param datetime' do
108
+ p = HaveAPI::Params.new(:input, MyResource::Index)
109
+ p.add_block Proc.new { datetime :p_datetime }
110
+ p.exec
111
+ expect(p.params.first.type).to eq(Datetime)
112
+ end
113
+
114
+ it 'has param param' do
115
+ p = HaveAPI::Params.new(:input, MyResource::Index)
116
+ p.add_block Proc.new { param :p_param, type: Integer }
117
+ p.exec
118
+ expect(p.params.first.type).to eq(Integer)
119
+ end
120
+
121
+ it 'has param resource' do
122
+ p = HaveAPI::Params.new(:input, MyResource::Index)
123
+ p.add_block Proc.new { resource MyResource }
124
+ p.exec
125
+ expect(p.params.first).to be_an_instance_of(HaveAPI::Parameters::Resource)
126
+ end
127
+
128
+ it 'patches params' do
129
+ p = HaveAPI::Params.new(:input, MyResource::Index)
130
+ p.add_block(Proc.new do
131
+ string :param1, label: 'Param 1'
132
+ string :param2, label: 'Param 2', desc: 'Implicit description'
133
+ end)
134
+ p.exec
135
+ p.patch(:param1, label: 'Better param 1')
136
+ p.patch(:param2, desc: 'Better description')
137
+ expect(p.params.first.label).to eq('Better param 1')
138
+ expect(p.params.second.desc).to eq('Better description')
139
+ end
140
+
141
+ it 'validates upon build' do
142
+ p = HaveAPI::Params.new(:output, MyResource::Index)
143
+ p.add_block Proc.new { resource MyResource }
144
+ p.exec
145
+ expect(p.params.first).to be_an_instance_of(HaveAPI::Parameters::Resource)
146
+ expect { p.validate_build }.to raise_error(RuntimeError)
147
+ end
148
+
149
+ it 'accepts valid input layout' do
150
+ p = HaveAPI::Params.new(:input, MyResource::Index)
151
+ p.add_block(Proc.new do
152
+ string :param1, required: true
153
+ string :param2
154
+ end)
155
+ p.exec
156
+
157
+ expect do
158
+ p.check_layout({
159
+ my_resource: {}
160
+ })
161
+ end.not_to raise_error
162
+ end
163
+
164
+ it 'rejects invalid input layout' do
165
+ p = HaveAPI::Params.new(:input, MyResource::Index)
166
+ p.add_block(Proc.new do
167
+ string :param1, required: true
168
+ string :param2
169
+ end)
170
+ p.exec
171
+
172
+ expect do
173
+ p.check_layout({
174
+ something_bad: {}
175
+ })
176
+ end.to raise_error(HaveAPI::ValidationError)
177
+ end
178
+
179
+ it 'indexes parameters by name' do
180
+ p = HaveAPI::Params.new(:input, MyResource::Index)
181
+ p.add_block(Proc.new do
182
+ string :param1
183
+ string :param2
184
+ end)
185
+ p.exec
186
+
187
+ expect(p[:param1]).to eq(p.params.first)
188
+ expect(p[:param2]).to eq(p.params.second)
189
+ end
190
+ end
@@ -0,0 +1,63 @@
1
+ describe HaveAPI::Resource do
2
+ class PluralTest < HaveAPI::Resource
3
+
4
+ end
5
+
6
+ class SingularTest < HaveAPI::Resource
7
+ singular true
8
+ end
9
+
10
+ it 'has correct obj_type' do
11
+ expect(PluralTest.obj_type).to eq(:resource)
12
+ expect(SingularTest.obj_type).to eq(:resource)
13
+ end
14
+
15
+ it 'has plural name' do
16
+ expect(PluralTest.resource_name).to eq('plural_tests')
17
+ end
18
+
19
+ it 'has singular name' do
20
+ expect(SingularTest.resource_name).to eq('singular_test')
21
+ end
22
+
23
+ class ComplexTest < HaveAPI::Resource
24
+ class Index < HaveAPI::Actions::Default::Index ; end
25
+ class Show < HaveAPI::Actions::Default::Show ; end
26
+ class Create < HaveAPI::Actions::Default::Create ; end
27
+ class Dummy ; end
28
+
29
+ class SubResource < HaveAPI::Resource
30
+ class Index < HaveAPI::Actions::Default::Index ; end
31
+ class Show < HaveAPI::Actions::Default::Show ; end
32
+ end
33
+ end
34
+
35
+ it 'iterates over actions' do
36
+ actions = []
37
+
38
+ ComplexTest.actions do |a|
39
+ actions << a
40
+ end
41
+
42
+ expect(actions).to contain_exactly(
43
+ ComplexTest::Index,
44
+ ComplexTest::Show,
45
+ ComplexTest::Create
46
+ )
47
+ end
48
+
49
+ it 'iterates over resources' do
50
+ resources = []
51
+
52
+ ComplexTest.resources do |r|
53
+ resources << r
54
+ end
55
+
56
+ expect(resources).to contain_exactly(ComplexTest::SubResource)
57
+ end
58
+
59
+ it 'defines and returns resource-wide params' do
60
+ ComplexTest.params(:name) { 'executed' }
61
+ expect(ComplexTest.params(:name).call).to eq('executed')
62
+ end
63
+ end
@@ -0,0 +1,21 @@
1
+ require 'require_all'
2
+ require_relative '../lib/haveapi'
3
+ require_rel '../lib/haveapi/spec/*.rb'
4
+
5
+ module HaveAPI
6
+ module Spec
7
+ module API
8
+
9
+ end
10
+ end
11
+ end
12
+
13
+ require_rel 'api'
14
+
15
+ # Configure specs
16
+ RSpec.configure do |config|
17
+ config.order = 'random'
18
+
19
+ config.extend HaveAPI::Spec::ApiBuilder
20
+ config.include HaveAPI::Spec::SpecMethods
21
+ end
@@ -0,0 +1,29 @@
1
+ describe HaveAPI::Validators::Acceptance do
2
+ shared_examples(:all) do
3
+ it 'accepts correct value' do
4
+ expect(@v.valid?('foo')).to be true
5
+ end
6
+
7
+ it "rejects incorrect value" do
8
+ expect(@v.valid?('bar')).to be false
9
+ end
10
+ end
11
+
12
+ context 'short form' do
13
+ before(:each) do
14
+ @v = HaveAPI::Validators::Acceptance.new(:accept, 'foo')
15
+ end
16
+
17
+ include_examples :all
18
+ end
19
+
20
+ context 'full form' do
21
+ before(:each) do
22
+ @v = HaveAPI::Validators::Acceptance.new(:accept, {
23
+ value: 'foo'
24
+ })
25
+ end
26
+
27
+ include_examples :all
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ describe HaveAPI::Validators::Confirmation do
2
+ shared_examples(:all) do
3
+ it 'accepts the same value' do
4
+ expect(@v.validate('foo', {other_param: 'foo'})).to be true
5
+ end
6
+
7
+ it "rejects a different value" do
8
+ expect(@v.validate('bar', {other_param: 'foo'})).to be false
9
+ end
10
+ end
11
+
12
+ context 'short form' do
13
+ before(:each) do
14
+ @v = HaveAPI::Validators::Confirmation.new(:confirm, :other_param)
15
+ end
16
+
17
+ include_examples :all
18
+ end
19
+
20
+ context 'full form' do
21
+ before(:each) do
22
+ @v = HaveAPI::Validators::Confirmation.new(:confirm, {
23
+ param: :other_param
24
+ })
25
+ end
26
+
27
+ include_examples :all
28
+ end
29
+
30
+ context 'with equal = false' do
31
+ before(:each) do
32
+ @v = HaveAPI::Validators::Confirmation.new(:confirm, {
33
+ param: :other_param,
34
+ equal: false
35
+ })
36
+ end
37
+
38
+ it 'rejects the same value' do
39
+ expect(@v.validate('foo', {other_param: 'foo'})).to be false
40
+ end
41
+
42
+ it 'accepts a different value' do
43
+ expect(@v.validate('bar', {other_param: 'foo'})).to be true
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,6 @@
1
+ describe HaveAPI::Validators::Custom do
2
+ it 'always passes' do
3
+ v = HaveAPI::Validators::Custom.new(:validate, 'some custom validation')
4
+ expect(v.valid?('WHATEVER')).to be true
5
+ end
6
+ end
@@ -0,0 +1,32 @@
1
+ describe HaveAPI::Validators::Exclusion do
2
+ shared_examples(:all) do
3
+ it 'rejects a listed value' do
4
+ expect(@v.valid?('one')).to be false
5
+ expect(@v.valid?('two')).to be false
6
+ expect(@v.valid?('three')).to be false
7
+ end
8
+
9
+ it "accepts an unlisted value" do
10
+ expect(@v.valid?('zero')).to be true
11
+ expect(@v.valid?('four')).to be true
12
+ end
13
+ end
14
+
15
+ context 'short form' do
16
+ before(:each) do
17
+ @v = HaveAPI::Validators::Exclusion.new(:exclude, %w(one two three))
18
+ end
19
+
20
+ include_examples :all
21
+ end
22
+
23
+ context 'full form' do
24
+ before(:each) do
25
+ @v = HaveAPI::Validators::Exclusion.new(:exclude, {
26
+ values: %w(one two three)
27
+ })
28
+ end
29
+
30
+ include_examples :all
31
+ end
32
+ end
@@ -0,0 +1,54 @@
1
+ describe HaveAPI::Validators::Format do
2
+ shared_examples(:all) do
3
+ it 'accepts a value that matches the regexp' do
4
+ expect(@v.valid?('aab')).to be true
5
+ expect(@v.valid?('aacacb')).to be true
6
+ end
7
+
8
+ it "rejects a value that does not match the regexp" do
9
+ expect(@v.valid?('aacac')).to be false
10
+ expect(@v.valid?('bacacb')).to be false
11
+ expect(@v.valid?('b')).to be false
12
+ end
13
+ end
14
+
15
+ context 'with match = true' do
16
+ context 'short form' do
17
+ before(:each) do
18
+ @v = HaveAPI::Validators::Format.new(:format, /^a[^b]+b$/)
19
+ end
20
+
21
+ include_examples :all
22
+ end
23
+
24
+ context 'full form' do
25
+ before(:each) do
26
+ @v = HaveAPI::Validators::Format.new(:format, {
27
+ rx: /^a[^b]+b$/
28
+ })
29
+ end
30
+
31
+ include_examples :all
32
+ end
33
+ end
34
+
35
+ context 'with match = false' do
36
+ before(:each) do
37
+ @v = HaveAPI::Validators::Format.new(:format, {
38
+ rx: /^a[^b]+b$/,
39
+ match: false
40
+ })
41
+ end
42
+
43
+ it 'rejects a value that matches the regexp' do
44
+ expect(@v.valid?('aab')).to be false
45
+ expect(@v.valid?('aacacb')).to be false
46
+ end
47
+
48
+ it "accepts a value if it does not match the regexp" do
49
+ expect(@v.valid?('aacac')).to be true
50
+ expect(@v.valid?('bacacb')).to be true
51
+ expect(@v.valid?('b')).to be true
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,43 @@
1
+ describe HaveAPI::Validators::Inclusion do
2
+ shared_examples(:all) do
3
+ it 'accepts a listed value' do
4
+ expect(@v.valid?('one')).to be true
5
+ expect(@v.valid?('two')).to be true
6
+ expect(@v.valid?('three')).to be true
7
+ end
8
+
9
+ it "rejects an unlisted value" do
10
+ expect(@v.valid?('zero')).to be false
11
+ expect(@v.valid?('four')).to be false
12
+ end
13
+ end
14
+
15
+ [
16
+ %w(one two three),
17
+ {
18
+ one: 'Fancy one',
19
+ two: 'Fancy two',
20
+ three: 'Fancy three'
21
+ }
22
+ ].each do |include|
23
+ context "with include as a '#{include.class}'" do
24
+ context 'short form' do
25
+ before(:each) do
26
+ @v = HaveAPI::Validators::Inclusion.new(:include, %w(one two three))
27
+ end
28
+
29
+ include_examples :all
30
+ end
31
+
32
+ context 'full form' do
33
+ before(:each) do
34
+ @v = HaveAPI::Validators::Inclusion.new(:include, {
35
+ values: %w(one two three)
36
+ })
37
+ end
38
+
39
+ include_examples :all
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,45 @@
1
+ describe HaveAPI::Validators::Length do
2
+ it 'does not allow to mix min/max with equals' do
3
+ expect do
4
+ HaveAPI::Validators::Length.new(:length, {min: 33, equals: 42})
5
+ end.to raise_error(RuntimeError)
6
+ end
7
+
8
+ it 'requires one of min, max or equals' do
9
+ expect do
10
+ HaveAPI::Validators::Length.new(:length, {})
11
+ end.to raise_error(RuntimeError)
12
+ end
13
+
14
+ it 'checks minimum' do
15
+ v = HaveAPI::Validators::Length.new(:length, {min: 2})
16
+ expect(v.valid?('a'*1)).to be false
17
+ expect(v.valid?('a'*2)).to be true
18
+ expect(v.valid?('a'*33)).to be true
19
+ end
20
+
21
+ it 'checks maximum' do
22
+ v = HaveAPI::Validators::Length.new(:length, {max: 5})
23
+ expect(v.valid?('a'*4)).to be true
24
+ expect(v.valid?('a'*5)).to be true
25
+ expect(v.valid?('a'*6)).to be false
26
+ expect(v.valid?('a'*11)).to be false
27
+ end
28
+
29
+ it 'checks range' do
30
+ v = HaveAPI::Validators::Length.new(:length, {min: 3, max: 6})
31
+ expect(v.valid?('a'*2)).to be false
32
+ expect(v.valid?('a'*3)).to be true
33
+ expect(v.valid?('a'*4)).to be true
34
+ expect(v.valid?('a'*5)).to be true
35
+ expect(v.valid?('a'*6)).to be true
36
+ expect(v.valid?('a'*7)).to be false
37
+ end
38
+
39
+ it 'check a specific length' do
40
+ v = HaveAPI::Validators::Length.new(:length, {equals: 4})
41
+ expect(v.valid?('a'*2)).to be false
42
+ expect(v.valid?('a'*4)).to be true
43
+ expect(v.valid?('a'*5)).to be false
44
+ end
45
+ end
@@ -0,0 +1,70 @@
1
+ describe HaveAPI::Validators::Numericality do
2
+ it 'cannot be both even and odd at the same time' do
3
+ expect do
4
+ HaveAPI::Validators::Numericality.new(:number, {odd: true, even: true})
5
+ end.to raise_error(RuntimeError)
6
+ end
7
+
8
+ it 'checks minimum' do
9
+ v = HaveAPI::Validators::Numericality.new(:number, {min: 5})
10
+ expect(v.valid?(4)).to be false
11
+ expect(v.valid?(5)).to be true
12
+ expect(v.valid?(6)).to be true
13
+ end
14
+
15
+ it 'checks maximum' do
16
+ v = HaveAPI::Validators::Numericality.new(:number, {max: 50})
17
+ expect(v.valid?(100)).to be false
18
+ expect(v.valid?(51)).to be false
19
+ expect(v.valid?(50)).to be true
20
+ expect(v.valid?(40)).to be true
21
+ end
22
+
23
+ it 'checks that x % y = 0' do
24
+ v = HaveAPI::Validators::Numericality.new(:number, {mod: 2})
25
+ expect(v.valid?(3)).to be false
26
+ expect(v.valid?(15)).to be false
27
+ expect(v.valid?(0)).to be true
28
+ expect(v.valid?(2)).to be true
29
+ expect(v.valid?(48)).to be true
30
+ end
31
+
32
+ it 'checks that the number is in a step' do
33
+ v = HaveAPI::Validators::Numericality.new(:number, {step: 3})
34
+ expect(v.valid?(4)).to be false
35
+ expect(v.valid?(14)).to be false
36
+ expect(v.valid?(0)).to be true
37
+ expect(v.valid?(3)).to be true
38
+ expect(v.valid?(6)).to be true
39
+ expect(v.valid?(9)).to be true
40
+ end
41
+
42
+ it 'checks that the number is in a step with a minimum' do
43
+ v = HaveAPI::Validators::Numericality.new(:number, {min: 5, step: 3})
44
+ expect(v.valid?(0)).to be false
45
+ expect(v.valid?(3)).to be false
46
+ expect(v.valid?(4)).to be false
47
+ expect(v.valid?(12)).to be false
48
+ expect(v.valid?(15)).to be false
49
+ expect(v.valid?(5)).to be true
50
+ expect(v.valid?(8)).to be true
51
+ expect(v.valid?(11)).to be true
52
+ expect(v.valid?(14)).to be true
53
+ end
54
+
55
+ it 'checks that the number is even' do
56
+ v = HaveAPI::Validators::Numericality.new(:number, {even: true})
57
+ expect(v.valid?(1)).to be false
58
+ expect(v.valid?(3)).to be false
59
+ expect(v.valid?(0)).to be true
60
+ expect(v.valid?(2)).to be true
61
+ end
62
+
63
+ it 'checks that the number is odd' do
64
+ v = HaveAPI::Validators::Numericality.new(:number, {odd: true})
65
+ expect(v.valid?(1)).to be true
66
+ expect(v.valid?(3)).to be true
67
+ expect(v.valid?(0)).to be false
68
+ expect(v.valid?(2)).to be false
69
+ end
70
+ end
@@ -0,0 +1,47 @@
1
+ describe HaveAPI::Validators::Presence do
2
+ shared_examples(:all) do
3
+ it 'accepts a present value' do
4
+ expect(@v.valid?('foo')).to be true
5
+ end
6
+
7
+ it 'rejects a missing or empty value' do
8
+ expect(@v.valid?(nil)).to be false
9
+ expect(@v.valid?('')).to be false
10
+ expect(@v.valid?(" \t"*4)).to be false
11
+ end
12
+ end
13
+
14
+ context 'with empty = true' do
15
+ context 'in short form' do
16
+ before(:each) do
17
+ @v = HaveAPI::Validators::Presence.new(:required, true)
18
+ end
19
+
20
+ include_examples :all
21
+ end
22
+
23
+ context 'in full form' do
24
+ before(:each) do
25
+ @v = HaveAPI::Validators::Presence.new(:required, {})
26
+ end
27
+
28
+ include_examples :all
29
+ end
30
+ end
31
+
32
+ context 'with empty = false' do
33
+ before(:each) do
34
+ @v = HaveAPI::Validators::Presence.new(:required, {empty: true})
35
+ end
36
+
37
+ it 'accepts a present value' do
38
+ expect(@v.valid?('foo')).to be true
39
+ end
40
+
41
+ it 'rejects a missing or an empty value' do
42
+ expect(@v.valid?(nil)).to be false
43
+ expect(@v.valid?('')).to be true
44
+ expect(@v.valid?(" \t"*4)).to be true
45
+ end
46
+ end
47
+ end