haveapi 0.26.4 → 0.27.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 +4 -4
- data/.rspec +1 -0
- data/Gemfile +7 -3
- data/haveapi.gemspec +1 -1
- data/lib/haveapi/action.rb +1 -1
- data/lib/haveapi/authentication/base.rb +2 -0
- data/lib/haveapi/authentication/oauth2/provider.rb +10 -2
- data/lib/haveapi/authentication/token/provider.rb +25 -1
- data/lib/haveapi/model_adapters/active_record.rb +61 -4
- data/lib/haveapi/parameters/typed.rb +94 -10
- data/lib/haveapi/params.rb +6 -1
- data/lib/haveapi/resource.rb +1 -1
- data/lib/haveapi/server.rb +10 -1
- data/lib/haveapi/spec/api_builder.rb +8 -3
- data/lib/haveapi/spec/spec_methods.rb +20 -10
- data/lib/haveapi/version.rb +1 -1
- data/spec/action/authorize_spec.rb +317 -0
- data/spec/action/dsl_spec.rb +98 -100
- data/spec/action/runtime_spec.rb +207 -0
- data/spec/action_state_spec.rb +301 -0
- data/spec/authentication/basic_spec.rb +108 -0
- data/spec/authentication/oauth2_spec.rb +127 -0
- data/spec/authentication/token_spec.rb +233 -0
- data/spec/authorization_spec.rb +23 -18
- data/spec/common_spec.rb +19 -17
- data/spec/documentation/auth_filtering_spec.rb +111 -0
- data/spec/documentation_spec.rb +165 -2
- data/spec/envelope_spec.rb +5 -9
- data/spec/extensions/action_exceptions_spec.rb +163 -0
- data/spec/hooks_spec.rb +32 -38
- data/spec/model_adapters/active_record_spec.rb +411 -0
- data/spec/parameters/typed_spec.rb +54 -1
- data/spec/params_spec.rb +27 -25
- data/spec/resource_spec.rb +36 -22
- data/spec/server/integration_spec.rb +71 -0
- data/spec/spec_helper.rb +2 -2
- data/spec/validators/acceptance_spec.rb +10 -12
- data/spec/validators/confirmation_spec.rb +14 -16
- data/spec/validators/custom_spec.rb +1 -1
- data/spec/validators/exclusion_spec.rb +13 -15
- data/spec/validators/format_spec.rb +20 -22
- data/spec/validators/inclusion_spec.rb +13 -15
- data/spec/validators/length_spec.rb +6 -6
- data/spec/validators/numericality_spec.rb +10 -10
- data/spec/validators/presence_spec.rb +16 -22
- data/test_support/client_test_api.rb +583 -0
- data/test_support/client_test_server.rb +59 -0
- metadata +16 -3
data/spec/resource_spec.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
module ResourceSpec
|
|
2
2
|
class PluralTest < HaveAPI::Resource
|
|
3
3
|
end
|
|
4
4
|
|
|
@@ -6,19 +6,6 @@ describe HaveAPI::Resource do
|
|
|
6
6
|
singular true
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
it 'has correct obj_type' do
|
|
10
|
-
expect(PluralTest.obj_type).to eq(:resource)
|
|
11
|
-
expect(SingularTest.obj_type).to eq(:resource)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
it 'has plural name' do
|
|
15
|
-
expect(PluralTest.resource_name).to eq('plural_tests')
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
it 'has singular name' do
|
|
19
|
-
expect(SingularTest.resource_name).to eq('singular_test')
|
|
20
|
-
end
|
|
21
|
-
|
|
22
9
|
class ComplexTest < HaveAPI::Resource
|
|
23
10
|
class Index < HaveAPI::Actions::Default::Index; end
|
|
24
11
|
class Show < HaveAPI::Actions::Default::Show; end
|
|
@@ -29,33 +16,60 @@ describe HaveAPI::Resource do
|
|
|
29
16
|
class Show < HaveAPI::Actions::Default::Show; end
|
|
30
17
|
end
|
|
31
18
|
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe HaveAPI::Resource do
|
|
22
|
+
it 'has correct obj_type' do
|
|
23
|
+
expect(ResourceSpec::PluralTest.obj_type).to eq(:resource)
|
|
24
|
+
expect(ResourceSpec::SingularTest.obj_type).to eq(:resource)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context 'when resource is plural' do
|
|
28
|
+
it 'has singular resource name' do
|
|
29
|
+
expect(ResourceSpec::PluralTest.resource_name).to eq('PluralTest')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'has plural rest name' do
|
|
33
|
+
expect(ResourceSpec::PluralTest.rest_name).to eq('plural_tests')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context 'when resource is singular' do
|
|
38
|
+
it 'has singular resource name' do
|
|
39
|
+
expect(ResourceSpec::SingularTest.resource_name).to eq('SingularTest')
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'has singular rest name' do
|
|
43
|
+
expect(ResourceSpec::SingularTest.rest_name).to eq('singular_test')
|
|
44
|
+
end
|
|
45
|
+
end
|
|
32
46
|
|
|
33
47
|
it 'iterates over actions' do
|
|
34
48
|
actions = []
|
|
35
49
|
|
|
36
|
-
ComplexTest.actions do |a|
|
|
50
|
+
ResourceSpec::ComplexTest.actions do |a|
|
|
37
51
|
actions << a
|
|
38
52
|
end
|
|
39
53
|
|
|
40
54
|
expect(actions).to contain_exactly(
|
|
41
|
-
ComplexTest::Index,
|
|
42
|
-
ComplexTest::Show,
|
|
43
|
-
ComplexTest::Create
|
|
55
|
+
ResourceSpec::ComplexTest::Index,
|
|
56
|
+
ResourceSpec::ComplexTest::Show,
|
|
57
|
+
ResourceSpec::ComplexTest::Create
|
|
44
58
|
)
|
|
45
59
|
end
|
|
46
60
|
|
|
47
61
|
it 'iterates over resources' do
|
|
48
62
|
resources = []
|
|
49
63
|
|
|
50
|
-
ComplexTest.resources do |r|
|
|
64
|
+
ResourceSpec::ComplexTest.resources do |r|
|
|
51
65
|
resources << r
|
|
52
66
|
end
|
|
53
67
|
|
|
54
|
-
expect(resources).to contain_exactly(ComplexTest::SubResource)
|
|
68
|
+
expect(resources).to contain_exactly(ResourceSpec::ComplexTest::SubResource)
|
|
55
69
|
end
|
|
56
70
|
|
|
57
71
|
it 'defines and returns resource-wide params' do
|
|
58
|
-
ComplexTest.params(:name) { 'executed' }
|
|
59
|
-
expect(ComplexTest.params(:name).call).to eq('executed')
|
|
72
|
+
ResourceSpec::ComplexTest.params(:name) { 'executed' }
|
|
73
|
+
expect(ResourceSpec::ComplexTest.params(:name).call).to eq('executed')
|
|
60
74
|
end
|
|
61
75
|
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe HaveAPI::Server do
|
|
4
|
+
describe 'integration' do
|
|
5
|
+
api do
|
|
6
|
+
define_resource(:Test) do
|
|
7
|
+
version 1
|
|
8
|
+
auth false
|
|
9
|
+
|
|
10
|
+
define_action(:Echo) do
|
|
11
|
+
http_method :post
|
|
12
|
+
authorize { allow }
|
|
13
|
+
|
|
14
|
+
input do
|
|
15
|
+
string :msg
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
output do
|
|
19
|
+
string :msg
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def exec
|
|
23
|
+
{ msg: params.dig(:test, :msg) }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
default_version 1
|
|
30
|
+
|
|
31
|
+
it 'returns 406 for unsupported Accept' do
|
|
32
|
+
header 'Accept', 'text/plain'
|
|
33
|
+
options '/v1/'
|
|
34
|
+
|
|
35
|
+
expect(last_response.status).to eq(406)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'returns 400 for invalid JSON' do
|
|
39
|
+
header 'Content-Type', 'application/json'
|
|
40
|
+
header 'Accept', 'application/json'
|
|
41
|
+
post '/v1/tests/echo', '{'
|
|
42
|
+
|
|
43
|
+
expect(last_response.status).to eq(400)
|
|
44
|
+
expect(api_response).not_to be_ok
|
|
45
|
+
expect(api_response.message).to match(/Bad JSON syntax/)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'returns JSON envelope for unknown route' do
|
|
49
|
+
header 'Accept', 'application/json'
|
|
50
|
+
get '/does-not-exist'
|
|
51
|
+
|
|
52
|
+
expect(last_response.status).to eq(404)
|
|
53
|
+
expect(api_response).not_to be_ok
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'handles CORS preflight OPTIONS' do
|
|
57
|
+
header 'Accept', 'application/json'
|
|
58
|
+
header 'Origin', 'https://example.com'
|
|
59
|
+
header 'Access-Control-Request-Method', 'POST'
|
|
60
|
+
header 'Access-Control-Request-Headers', 'X-Foo, Authorization'
|
|
61
|
+
options '/v1/'
|
|
62
|
+
|
|
63
|
+
expect(last_response.status).to eq(200)
|
|
64
|
+
|
|
65
|
+
headers = last_response.headers.transform_keys(&:downcase)
|
|
66
|
+
expect(headers['access-control-allow-origin']).to eq('*')
|
|
67
|
+
expect(headers['access-control-allow-methods']).to include('POST')
|
|
68
|
+
expect(headers['access-control-allow-headers']).to be_a(String)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
ENV['RACK_ENV'] ||= 'test'
|
|
2
|
+
|
|
1
3
|
require 'require_all'
|
|
2
4
|
require_relative '../lib/haveapi'
|
|
3
5
|
require_rel '../lib/haveapi/spec/*.rb'
|
|
@@ -9,8 +11,6 @@ module HaveAPI
|
|
|
9
11
|
end
|
|
10
12
|
end
|
|
11
13
|
|
|
12
|
-
require_rel 'api'
|
|
13
|
-
|
|
14
14
|
# Configure specs
|
|
15
15
|
RSpec.configure do |config|
|
|
16
16
|
config.order = 'random'
|
|
@@ -1,29 +1,27 @@
|
|
|
1
1
|
describe HaveAPI::Validators::Acceptance do
|
|
2
|
-
shared_examples(
|
|
2
|
+
shared_examples('all') do
|
|
3
3
|
it 'accepts correct value' do
|
|
4
|
-
expect(
|
|
4
|
+
expect(validator.valid?('foo')).to be true
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
it 'rejects incorrect value' do
|
|
8
|
-
expect(
|
|
8
|
+
expect(validator.valid?('bar')).to be false
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
context 'short form' do
|
|
13
|
-
|
|
14
|
-
@v = HaveAPI::Validators::Acceptance.new(:accept, 'foo')
|
|
15
|
-
end
|
|
12
|
+
context 'with short form' do
|
|
13
|
+
let(:validator) { described_class.new(:accept, 'foo') }
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
it_behaves_like 'all'
|
|
18
16
|
end
|
|
19
17
|
|
|
20
|
-
context 'full form' do
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
context 'with full form' do
|
|
19
|
+
let(:validator) do
|
|
20
|
+
described_class.new(:accept, {
|
|
23
21
|
value: 'foo'
|
|
24
22
|
})
|
|
25
23
|
end
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
it_behaves_like 'all'
|
|
28
26
|
end
|
|
29
27
|
end
|
|
@@ -1,46 +1,44 @@
|
|
|
1
1
|
describe HaveAPI::Validators::Confirmation do
|
|
2
|
-
shared_examples(
|
|
2
|
+
shared_examples('all') do
|
|
3
3
|
it 'accepts the same value' do
|
|
4
|
-
expect(
|
|
4
|
+
expect(validator.validate('foo', { other_param: 'foo' })).to be true
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
it 'rejects a different value' do
|
|
8
|
-
expect(
|
|
8
|
+
expect(validator.validate('bar', { other_param: 'foo' })).to be false
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
context 'short form' do
|
|
13
|
-
|
|
14
|
-
@v = HaveAPI::Validators::Confirmation.new(:confirm, :other_param)
|
|
15
|
-
end
|
|
12
|
+
context 'with short form' do
|
|
13
|
+
let(:validator) { described_class.new(:confirm, :other_param) }
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
it_behaves_like 'all'
|
|
18
16
|
end
|
|
19
17
|
|
|
20
|
-
context 'full form' do
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
context 'with full form' do
|
|
19
|
+
let(:validator) do
|
|
20
|
+
described_class.new(:confirm, {
|
|
23
21
|
param: :other_param
|
|
24
22
|
})
|
|
25
23
|
end
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
it_behaves_like 'all'
|
|
28
26
|
end
|
|
29
27
|
|
|
30
28
|
context 'with equal = false' do
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
let(:validator) do
|
|
30
|
+
described_class.new(:confirm, {
|
|
33
31
|
param: :other_param,
|
|
34
32
|
equal: false
|
|
35
33
|
})
|
|
36
34
|
end
|
|
37
35
|
|
|
38
36
|
it 'rejects the same value' do
|
|
39
|
-
expect(
|
|
37
|
+
expect(validator.validate('foo', { other_param: 'foo' })).to be false
|
|
40
38
|
end
|
|
41
39
|
|
|
42
40
|
it 'accepts a different value' do
|
|
43
|
-
expect(
|
|
41
|
+
expect(validator.validate('bar', { other_param: 'foo' })).to be true
|
|
44
42
|
end
|
|
45
43
|
end
|
|
46
44
|
end
|
|
@@ -1,32 +1,30 @@
|
|
|
1
1
|
describe HaveAPI::Validators::Exclusion do
|
|
2
|
-
shared_examples(
|
|
2
|
+
shared_examples('all') do
|
|
3
3
|
it 'rejects a listed value' do
|
|
4
|
-
expect(
|
|
5
|
-
expect(
|
|
6
|
-
expect(
|
|
4
|
+
expect(validator.valid?('one')).to be false
|
|
5
|
+
expect(validator.valid?('two')).to be false
|
|
6
|
+
expect(validator.valid?('three')).to be false
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
it 'accepts an unlisted value' do
|
|
10
|
-
expect(
|
|
11
|
-
expect(
|
|
10
|
+
expect(validator.valid?('zero')).to be true
|
|
11
|
+
expect(validator.valid?('four')).to be true
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
context 'short form' do
|
|
16
|
-
|
|
17
|
-
@v = HaveAPI::Validators::Exclusion.new(:exclude, %w[one two three])
|
|
18
|
-
end
|
|
15
|
+
context 'with short form' do
|
|
16
|
+
let(:validator) { described_class.new(:exclude, %w[one two three]) }
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
it_behaves_like 'all'
|
|
21
19
|
end
|
|
22
20
|
|
|
23
|
-
context 'full form' do
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
context 'with full form' do
|
|
22
|
+
let(:validator) do
|
|
23
|
+
described_class.new(:exclude, {
|
|
26
24
|
values: %w[one two three]
|
|
27
25
|
})
|
|
28
26
|
end
|
|
29
27
|
|
|
30
|
-
|
|
28
|
+
it_behaves_like 'all'
|
|
31
29
|
end
|
|
32
30
|
end
|
|
@@ -1,54 +1,52 @@
|
|
|
1
1
|
describe HaveAPI::Validators::Format do
|
|
2
|
-
shared_examples(
|
|
2
|
+
shared_examples('all') do
|
|
3
3
|
it 'accepts a value that matches the regexp' do
|
|
4
|
-
expect(
|
|
5
|
-
expect(
|
|
4
|
+
expect(validator.valid?('aab')).to be true
|
|
5
|
+
expect(validator.valid?('aacacb')).to be true
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
it 'rejects a value that does not match the regexp' do
|
|
9
|
-
expect(
|
|
10
|
-
expect(
|
|
11
|
-
expect(
|
|
9
|
+
expect(validator.valid?('aacac')).to be false
|
|
10
|
+
expect(validator.valid?('bacacb')).to be false
|
|
11
|
+
expect(validator.valid?('b')).to be false
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
context 'with match = true' do
|
|
16
|
-
context 'short form' do
|
|
17
|
-
|
|
18
|
-
@v = HaveAPI::Validators::Format.new(:format, /^a[^b]+b$/)
|
|
19
|
-
end
|
|
16
|
+
context 'with short form' do
|
|
17
|
+
let(:validator) { described_class.new(:format, /^a[^b]+b$/) }
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
it_behaves_like 'all'
|
|
22
20
|
end
|
|
23
21
|
|
|
24
|
-
context 'full form' do
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
context 'with full form' do
|
|
23
|
+
let(:validator) do
|
|
24
|
+
described_class.new(:format, {
|
|
27
25
|
rx: /^a[^b]+b$/
|
|
28
26
|
})
|
|
29
27
|
end
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
it_behaves_like 'all'
|
|
32
30
|
end
|
|
33
31
|
end
|
|
34
32
|
|
|
35
33
|
context 'with match = false' do
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
let(:validator) do
|
|
35
|
+
described_class.new(:format, {
|
|
38
36
|
rx: /^a[^b]+b$/,
|
|
39
37
|
match: false
|
|
40
38
|
})
|
|
41
39
|
end
|
|
42
40
|
|
|
43
41
|
it 'rejects a value that matches the regexp' do
|
|
44
|
-
expect(
|
|
45
|
-
expect(
|
|
42
|
+
expect(validator.valid?('aab')).to be false
|
|
43
|
+
expect(validator.valid?('aacacb')).to be false
|
|
46
44
|
end
|
|
47
45
|
|
|
48
46
|
it 'accepts a value if it does not match the regexp' do
|
|
49
|
-
expect(
|
|
50
|
-
expect(
|
|
51
|
-
expect(
|
|
47
|
+
expect(validator.valid?('aacac')).to be true
|
|
48
|
+
expect(validator.valid?('bacacb')).to be true
|
|
49
|
+
expect(validator.valid?('b')).to be true
|
|
52
50
|
end
|
|
53
51
|
end
|
|
54
52
|
end
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
describe HaveAPI::Validators::Inclusion do
|
|
2
|
-
shared_examples(
|
|
2
|
+
shared_examples('all') do
|
|
3
3
|
it 'accepts a listed value' do
|
|
4
|
-
expect(
|
|
5
|
-
expect(
|
|
6
|
-
expect(
|
|
4
|
+
expect(validator.valid?('one')).to be true
|
|
5
|
+
expect(validator.valid?('two')).to be true
|
|
6
|
+
expect(validator.valid?('three')).to be true
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
it 'rejects an unlisted value' do
|
|
10
|
-
expect(
|
|
11
|
-
expect(
|
|
10
|
+
expect(validator.valid?('zero')).to be false
|
|
11
|
+
expect(validator.valid?('four')).to be false
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
|
|
@@ -21,22 +21,20 @@ describe HaveAPI::Validators::Inclusion do
|
|
|
21
21
|
}
|
|
22
22
|
].each do |include|
|
|
23
23
|
context "with include as a '#{include.class}'" do
|
|
24
|
-
context 'short form' do
|
|
25
|
-
|
|
26
|
-
@v = HaveAPI::Validators::Inclusion.new(:include, %w[one two three])
|
|
27
|
-
end
|
|
24
|
+
context 'with short form' do
|
|
25
|
+
let(:validator) { described_class.new(:include, %w[one two three]) }
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
it_behaves_like 'all'
|
|
30
28
|
end
|
|
31
29
|
|
|
32
|
-
context 'full form' do
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
context 'with full form' do
|
|
31
|
+
let(:validator) do
|
|
32
|
+
described_class.new(:include, {
|
|
35
33
|
values: %w[one two three]
|
|
36
34
|
})
|
|
37
35
|
end
|
|
38
36
|
|
|
39
|
-
|
|
37
|
+
it_behaves_like 'all'
|
|
40
38
|
end
|
|
41
39
|
end
|
|
42
40
|
end
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
describe HaveAPI::Validators::Length do
|
|
2
2
|
it 'does not allow to mix min/max with equals' do
|
|
3
3
|
expect do
|
|
4
|
-
|
|
4
|
+
described_class.new(:length, { min: 33, equals: 42 })
|
|
5
5
|
end.to raise_error(RuntimeError)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
it 'requires one of min, max or equals' do
|
|
9
9
|
expect do
|
|
10
|
-
|
|
10
|
+
described_class.new(:length, {})
|
|
11
11
|
end.to raise_error(RuntimeError)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
it 'checks minimum' do
|
|
15
|
-
v =
|
|
15
|
+
v = described_class.new(:length, { min: 2 })
|
|
16
16
|
expect(v.valid?('a' * 1)).to be false
|
|
17
17
|
expect(v.valid?('a' * 2)).to be true
|
|
18
18
|
expect(v.valid?('a' * 33)).to be true
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
it 'checks maximum' do
|
|
22
|
-
v =
|
|
22
|
+
v = described_class.new(:length, { max: 5 })
|
|
23
23
|
expect(v.valid?('a' * 4)).to be true
|
|
24
24
|
expect(v.valid?('a' * 5)).to be true
|
|
25
25
|
expect(v.valid?('a' * 6)).to be false
|
|
@@ -27,7 +27,7 @@ describe HaveAPI::Validators::Length do
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
it 'checks range' do
|
|
30
|
-
v =
|
|
30
|
+
v = described_class.new(:length, { min: 3, max: 6 })
|
|
31
31
|
expect(v.valid?('a' * 2)).to be false
|
|
32
32
|
expect(v.valid?('a' * 3)).to be true
|
|
33
33
|
expect(v.valid?('a' * 4)).to be true
|
|
@@ -37,7 +37,7 @@ describe HaveAPI::Validators::Length do
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
it 'check a specific length' do
|
|
40
|
-
v =
|
|
40
|
+
v = described_class.new(:length, { equals: 4 })
|
|
41
41
|
expect(v.valid?('a' * 2)).to be false
|
|
42
42
|
expect(v.valid?('a' * 4)).to be true
|
|
43
43
|
expect(v.valid?('a' * 5)).to be false
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
describe HaveAPI::Validators::Numericality do
|
|
2
2
|
it 'cannot be both even and odd at the same time' do
|
|
3
3
|
expect do
|
|
4
|
-
|
|
4
|
+
described_class.new(:number, { odd: true, even: true })
|
|
5
5
|
end.to raise_error(RuntimeError)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
it 'checks minimum' do
|
|
9
|
-
v =
|
|
9
|
+
v = described_class.new(:number, { min: 5 })
|
|
10
10
|
expect(v.valid?(4)).to be false
|
|
11
11
|
expect(v.valid?(5)).to be true
|
|
12
12
|
expect(v.valid?(6)).to be true
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
it 'checks maximum' do
|
|
16
|
-
v =
|
|
16
|
+
v = described_class.new(:number, { max: 50 })
|
|
17
17
|
expect(v.valid?(100)).to be false
|
|
18
18
|
expect(v.valid?(51)).to be false
|
|
19
19
|
expect(v.valid?(50)).to be true
|
|
@@ -21,7 +21,7 @@ describe HaveAPI::Validators::Numericality do
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
it 'checks that x % y = 0' do
|
|
24
|
-
v =
|
|
24
|
+
v = described_class.new(:number, { mod: 2 })
|
|
25
25
|
expect(v.valid?(3)).to be false
|
|
26
26
|
expect(v.valid?(15)).to be false
|
|
27
27
|
expect(v.valid?(0)).to be true
|
|
@@ -30,7 +30,7 @@ describe HaveAPI::Validators::Numericality do
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
it 'checks that the number is in a step' do
|
|
33
|
-
v =
|
|
33
|
+
v = described_class.new(:number, { step: 3 })
|
|
34
34
|
expect(v.valid?(4)).to be false
|
|
35
35
|
expect(v.valid?(14)).to be false
|
|
36
36
|
expect(v.valid?(0)).to be true
|
|
@@ -40,7 +40,7 @@ describe HaveAPI::Validators::Numericality do
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
it 'checks that the number is in a step with a minimum' do
|
|
43
|
-
v =
|
|
43
|
+
v = described_class.new(:number, { min: 5, step: 3 })
|
|
44
44
|
expect(v.valid?(0)).to be false
|
|
45
45
|
expect(v.valid?(3)).to be false
|
|
46
46
|
expect(v.valid?(4)).to be false
|
|
@@ -53,7 +53,7 @@ describe HaveAPI::Validators::Numericality do
|
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
it 'checks that the number is even' do
|
|
56
|
-
v =
|
|
56
|
+
v = described_class.new(:number, { even: true })
|
|
57
57
|
expect(v.valid?(1)).to be false
|
|
58
58
|
expect(v.valid?(3)).to be false
|
|
59
59
|
expect(v.valid?(0)).to be true
|
|
@@ -61,7 +61,7 @@ describe HaveAPI::Validators::Numericality do
|
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
it 'checks that the number is odd' do
|
|
64
|
-
v =
|
|
64
|
+
v = described_class.new(:number, { odd: true })
|
|
65
65
|
expect(v.valid?(1)).to be true
|
|
66
66
|
expect(v.valid?(3)).to be true
|
|
67
67
|
expect(v.valid?(0)).to be false
|
|
@@ -69,12 +69,12 @@ describe HaveAPI::Validators::Numericality do
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
it 'checks number as string' do
|
|
72
|
-
v =
|
|
72
|
+
v = described_class.new(:number, { min: 5 })
|
|
73
73
|
expect(v.valid?('5')).to be true
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
it 'rejects a string that is not a number' do
|
|
77
|
-
v =
|
|
77
|
+
v = described_class.new(:number, { min: 5 })
|
|
78
78
|
expect(v.valid?('abc')).to be false
|
|
79
79
|
end
|
|
80
80
|
end
|
|
@@ -1,47 +1,41 @@
|
|
|
1
1
|
describe HaveAPI::Validators::Presence do
|
|
2
|
-
shared_examples(
|
|
2
|
+
shared_examples('all') do
|
|
3
3
|
it 'accepts a present value' do
|
|
4
|
-
expect(
|
|
4
|
+
expect(validator.valid?('foo')).to be true
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
it 'rejects a missing or empty value' do
|
|
8
|
-
expect(
|
|
9
|
-
expect(
|
|
10
|
-
expect(
|
|
8
|
+
expect(validator.valid?(nil)).to be false
|
|
9
|
+
expect(validator.valid?('')).to be false
|
|
10
|
+
expect(validator.valid?(" \t" * 4)).to be false
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
context 'with empty = true' do
|
|
15
|
-
context '
|
|
16
|
-
|
|
17
|
-
@v = HaveAPI::Validators::Presence.new(:required, true)
|
|
18
|
-
end
|
|
15
|
+
context 'with short form' do
|
|
16
|
+
let(:validator) { described_class.new(:required, true) }
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
it_behaves_like 'all'
|
|
21
19
|
end
|
|
22
20
|
|
|
23
|
-
context '
|
|
24
|
-
|
|
25
|
-
@v = HaveAPI::Validators::Presence.new(:required, {})
|
|
26
|
-
end
|
|
21
|
+
context 'with full form' do
|
|
22
|
+
let(:validator) { described_class.new(:required, {}) }
|
|
27
23
|
|
|
28
|
-
|
|
24
|
+
it_behaves_like 'all'
|
|
29
25
|
end
|
|
30
26
|
end
|
|
31
27
|
|
|
32
28
|
context 'with empty = false' do
|
|
33
|
-
|
|
34
|
-
@v = HaveAPI::Validators::Presence.new(:required, { empty: true })
|
|
35
|
-
end
|
|
29
|
+
let(:validator) { described_class.new(:required, { empty: true }) }
|
|
36
30
|
|
|
37
31
|
it 'accepts a present value' do
|
|
38
|
-
expect(
|
|
32
|
+
expect(validator.valid?('foo')).to be true
|
|
39
33
|
end
|
|
40
34
|
|
|
41
35
|
it 'rejects a missing or an empty value' do
|
|
42
|
-
expect(
|
|
43
|
-
expect(
|
|
44
|
-
expect(
|
|
36
|
+
expect(validator.valid?(nil)).to be false
|
|
37
|
+
expect(validator.valid?('')).to be true
|
|
38
|
+
expect(validator.valid?(" \t" * 4)).to be true
|
|
45
39
|
end
|
|
46
40
|
end
|
|
47
41
|
end
|