parameters_schema 0.42

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ require 'active_support/core_ext/hash/indifferent_access'
2
+ require 'active_support/core_ext/object/blank'
3
+ require 'active_support/core_ext/object/try'
4
+ require 'date'
5
+ require 'parameters_schema/core_ext'
6
+ require 'parameters_schema/options'
7
+ require 'parameters_schema/exceptions'
8
+ require 'parameters_schema/schema'
data/test/helpers.rb ADDED
@@ -0,0 +1,56 @@
1
+ module ActiveSupport
2
+ class HashWithIndifferentAccess < Hash
3
+ def must_equal_hash(other)
4
+ self.must_equal(other.with_indifferent_access)
5
+ end
6
+ end
7
+ end
8
+
9
+ module ParametersSchema
10
+ class Schema
11
+ def must_allow(values)
12
+ [values].flatten.each do |value|
13
+ if value.kind_of?(Range)
14
+ value.each do |v|
15
+ execute_must_allow(v)
16
+ end
17
+ else
18
+ execute_must_allow(value)
19
+ end
20
+ end
21
+
22
+ self
23
+ end
24
+
25
+ def must_deny(values, error_code = ParametersSchema::ErrorCode::DISALLOWED)
26
+ [values].flatten.each do |value|
27
+ if value.kind_of?(Range)
28
+ value.each do |v|
29
+ execute_must_deny(v, error_code)
30
+ end
31
+ else
32
+ execute_must_deny(value, error_code)
33
+ end
34
+ end
35
+
36
+ self
37
+ end
38
+
39
+ private
40
+
41
+ def execute_must_allow(value)
42
+ self
43
+ .validate!(potatoe: value)
44
+ .must_equal_hash(potatoe: value)
45
+ end
46
+
47
+ def execute_must_deny(value, error_code)
48
+ Proc.new do
49
+ self
50
+ .validate!(potatoe: value)
51
+ end
52
+ .must_raise(ParametersSchema::InvalidParameters)
53
+ .errors.must_equal_hash(potatoe: error_code)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,74 @@
1
+ require 'minitest/autorun'
2
+ require 'parameters_schema'
3
+ require_relative 'helpers'
4
+
5
+ describe 'Skipping parameters' do
6
+ before do
7
+ ParametersSchema::Options.reset_defaults
8
+
9
+ @schema = ParametersSchema::Schema.new do
10
+ param :potatoe
11
+ end
12
+ end
13
+
14
+ it 'skip default parameters in a Rails context' do
15
+ @schema
16
+ .validate!(potatoe: 'Ac Belmont', controller: 'potatoes', action: 'create', format: 'json')
17
+ .must_equal_hash(potatoe: 'Ac Belmont')
18
+ end
19
+
20
+ it 'redefines parameters to skip' do
21
+ ParametersSchema::Options.skip_parameters = [:banana]
22
+
23
+ @schema
24
+ .validate!(potatoe: 'Ac Belmont', banana: 'Cavendish')
25
+ .must_equal_hash(potatoe: 'Ac Belmont')
26
+
27
+ Proc
28
+ .new{ @schema.validate!(potatoe: 'Ac Belmont', controller: 'potatoes', action: 'create', format: 'json') }
29
+ .must_raise(ParametersSchema::InvalidParameters)
30
+ end
31
+
32
+ it 'augments parameters to skip' do
33
+ ParametersSchema::Options.skip_parameters = ParametersSchema::Options.skip_parameters + [:banana]
34
+ @schema
35
+ .validate!(potatoe: 'Ac Belmont', banana: 'Cavendish', controller: 'potatoes', action: 'create', format: 'json')
36
+ .must_equal_hash(potatoe: 'Ac Belmont')
37
+ end
38
+ end
39
+
40
+ describe 'Empty keyword' do
41
+ before do
42
+ ParametersSchema::Options.reset_defaults
43
+
44
+ @schema = ParametersSchema::Schema.new do
45
+ param :potatoe, allow: :empty
46
+ end
47
+ end
48
+
49
+ it 'uses the default value' do
50
+ ParametersSchema::Schema.new do
51
+ param :potatoe, allow: :empty
52
+ end
53
+ .validate!(potatoe: '')
54
+ .must_equal_hash(potatoe: '')
55
+ end
56
+
57
+ it 'redefines the value' do
58
+ ParametersSchema::Options.empty_keyword = :allow_empty
59
+
60
+ ParametersSchema::Schema.new do
61
+ param :potatoe, allow: :allow_empty
62
+ end
63
+ .validate!(potatoe: '')
64
+ .must_equal_hash(potatoe: '')
65
+
66
+ Proc.new do
67
+ ParametersSchema::Schema.new do
68
+ param :potatoe, allow: :empty
69
+ end.validate!(potatoe: '')
70
+ end
71
+ .must_raise(ParametersSchema::InvalidParameters)
72
+ .errors.must_equal_hash(potatoe: ParametersSchema::ErrorCode::EMPTY)
73
+ end
74
+ end
@@ -0,0 +1,114 @@
1
+ require 'minitest/autorun'
2
+ require 'parameters_schema'
3
+ require_relative 'helpers'
4
+
5
+ describe 'Allow and Deny' do
6
+ before do
7
+ ParametersSchema::Options.reset_defaults
8
+ end
9
+
10
+ it 'allows :any and denies :none by default' do
11
+ [{}, { allow: :any }, { deny: :none }, { allow: :any, deny: :none }].each do |options|
12
+ schema = ParametersSchema::Schema.new do
13
+ param :potatoe, options.merge(type: Fixnum)
14
+ end
15
+ .must_allow((-10..10))
16
+ end
17
+ end
18
+
19
+ it 'allows multiple :allow values' do
20
+ schema = ParametersSchema::Schema.new do
21
+ param :potatoe, type: Fixnum, allow: [(1..2), (4..5)]
22
+ end
23
+ .must_allow([1, 2, 4, 5])
24
+ .must_deny(3)
25
+ end
26
+
27
+ it 'allows multiple :deny values' do
28
+ schema = ParametersSchema::Schema.new do
29
+ param :potatoe, type: Fixnum, deny: [(1..2), (4..5)]
30
+ end
31
+ .must_allow([-1, 0, 3, 6, 7])
32
+ .must_deny([1, 2, 4, 5])
33
+ end
34
+
35
+ it 'gives priority to :any and :none in multiple :allow values' do
36
+ schema = ParametersSchema::Schema.new do
37
+ param :potatoe, type: Fixnum, allow: [(1..2), :any]
38
+ end
39
+ .must_allow((-10..10))
40
+
41
+ schema = ParametersSchema::Schema.new do
42
+ param :potatoe, type: Fixnum, allow: [(1..2), :none]
43
+ end
44
+ .must_deny((-10..10))
45
+ end
46
+
47
+ it 'gives priority to :any and :none in multiple :deny values' do
48
+ schema = ParametersSchema::Schema.new do
49
+ param :potatoe, type: Fixnum, deny: [(1..2), :none]
50
+ end
51
+ .must_allow((-10..10))
52
+
53
+ schema = ParametersSchema::Schema.new do
54
+ param :potatoe, type: Fixnum, deny: [(1..2), :any]
55
+ end
56
+ .must_deny((-10..10))
57
+ end
58
+
59
+ it 'when using an array, the :allow is applied on the array values' do
60
+ schema = ParametersSchema::Schema.new do
61
+ param :potatoe, type: Fixnum, array: true, allow: (1..3)
62
+ end
63
+
64
+ schema
65
+ .validate!(potatoe: [1, 2, 3, 2, 1])
66
+ .must_equal_hash(potatoe: [1, 2, 3, 2, 1])
67
+
68
+ Proc.new do
69
+ schema.validate!(potatoe: [1, 2, 3, 2, 1, 0])
70
+ end
71
+ .must_raise(ParametersSchema::InvalidParameters)
72
+ .errors.must_equal_hash(potatoe: ParametersSchema::ErrorCode::DISALLOWED)
73
+ end
74
+
75
+ it 'when using an array, the :deny is applied on the array values' do
76
+ schema = ParametersSchema::Schema.new do
77
+ param :potatoe, type: Fixnum, array: true, deny: (1..3)
78
+ end
79
+
80
+ schema
81
+ .validate!(potatoe: [-1, 0, 4, 5, 6])
82
+ .must_equal_hash(potatoe: [-1, 0, 4, 5, 6])
83
+
84
+ Proc.new do
85
+ schema.validate!(potatoe: [-1, 0, 4, 5, 6, 1])
86
+ end
87
+ .must_raise(ParametersSchema::InvalidParameters)
88
+ .errors.must_equal_hash(potatoe: ParametersSchema::ErrorCode::DISALLOWED)
89
+ end
90
+
91
+ it 'allows a subset of values defined by a range' do
92
+ schema = ParametersSchema::Schema.new do
93
+ param :potatoe, type: Fixnum, allow: (1..10)
94
+ end
95
+ .must_allow((1..10))
96
+ .must_deny(((-10..0).to_a + (11..20).to_a))
97
+ end
98
+
99
+ it 'allows a subset of values by choices' do
100
+ schema = ParametersSchema::Schema.new do
101
+ param :potatoe, allow: ['a', 'b', 'c']
102
+ end
103
+ .must_allow(['a', 'b', 'c'])
104
+ .must_deny('d')
105
+ end
106
+
107
+ it 'allows a subset of values by regex' do
108
+ schema = ParametersSchema::Schema.new do
109
+ param :potatoe, allow: /^[A-Z]+$/
110
+ end
111
+ .must_allow(['A', 'BB', 'CDE'])
112
+ .must_deny(['a', 'Aa', 'F1'])
113
+ end
114
+ end
@@ -0,0 +1,30 @@
1
+ require 'minitest/autorun'
2
+ require 'parameters_schema'
3
+ require_relative 'helpers'
4
+
5
+ describe 'Allow empty' do
6
+ before do
7
+ ParametersSchema::Options.reset_defaults
8
+ end
9
+
10
+ it 'requires a non-empty value by default' do
11
+ ParametersSchema::Schema.new do
12
+ param :potatoe
13
+ end
14
+ .must_deny('', ParametersSchema::ErrorCode::EMPTY)
15
+ end
16
+
17
+ it 'can be set to accept empty value' do
18
+ ParametersSchema::Schema.new do
19
+ param :potatoe, allow: :empty
20
+ end
21
+ .must_allow('')
22
+ end
23
+
24
+ it 'when set to accept empty, it still reject nil value' do
25
+ ParametersSchema::Schema.new do
26
+ param :potatoe, allow: :empty
27
+ end
28
+ .must_deny(nil, ParametersSchema::ErrorCode::NIL)
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ require 'minitest/autorun'
2
+ require 'parameters_schema'
3
+ require_relative 'helpers'
4
+
5
+ describe 'Allow nil' do
6
+ before do
7
+ ParametersSchema::Options.reset_defaults
8
+
9
+ @schema = ParametersSchema::Schema.new do
10
+ param :potatoe
11
+ end
12
+ end
13
+
14
+ it 'requires a non-nil value by default' do
15
+ ParametersSchema::Schema.new do
16
+ param :potatoe
17
+ end
18
+ .must_deny(nil, ParametersSchema::ErrorCode::NIL)
19
+ end
20
+
21
+ it 'can be set to accept nil' do
22
+ ParametersSchema::Schema.new do
23
+ param :potatoe, allow: :nil
24
+ end
25
+ .must_allow(nil)
26
+ end
27
+
28
+ it 'when set to accept nil, it still reject empty value' do
29
+ ParametersSchema::Schema.new do
30
+ param :potatoe, allow: :nil
31
+ end
32
+ .must_deny('', ParametersSchema::ErrorCode::EMPTY)
33
+ end
34
+ end
@@ -0,0 +1,90 @@
1
+ require 'minitest/autorun'
2
+ require 'parameters_schema'
3
+ require_relative 'helpers'
4
+
5
+ describe 'Object' do
6
+ it 'creates a sub-schema for objects' do
7
+ ParametersSchema::Schema.new do
8
+ param :potatoe do
9
+ param :name
10
+ end
11
+ end
12
+ .must_allow({ name: 'Eramosa' })
13
+ end
14
+
15
+ it 'creates a as many sub-schemas as needed' do
16
+ schema = ParametersSchema::Schema.new do
17
+ param :potatoe do
18
+ param :quantity, type: Fixnum
19
+ param :description do
20
+ param :name
21
+ param :local, type: :boolean
22
+ end
23
+ end
24
+ end
25
+
26
+ schema
27
+ .validate!(potatoe: { quantity: '10', description: { name: 'Eramosa', local: 't' } })
28
+ .must_equal_hash(potatoe: { quantity: 10, description: { name: 'Eramosa', local: true } })
29
+ end
30
+
31
+ it 'allows an empty sub-schema' do
32
+ schema = ParametersSchema::Schema.new do
33
+ param :potatoe do end
34
+ end
35
+ .must_deny(nil, ParametersSchema::ErrorCode::NIL)
36
+ .must_deny({}, ParametersSchema::ErrorCode::EMPTY)
37
+
38
+ Proc
39
+ .new{ schema.validate!(potatoe: { name: 'Eramosa' }) }
40
+ .must_raise(ParametersSchema::InvalidParameters)
41
+ .errors.must_equal_hash(potatoe: { name: ParametersSchema::ErrorCode::UNKNOWN })
42
+ end
43
+
44
+ it 'can be embeded in array' do
45
+ [{ array: true}, type: { Array => Hash }].each do |array_format|
46
+ schema = ParametersSchema::Schema.new do
47
+ param :potatoes, array_format do
48
+ param :name
49
+ end
50
+ end
51
+
52
+ schema
53
+ .validate!(potatoes: [{ name: 'Ac Belmont' }, { name: 'Eramosa' }])
54
+ .must_equal_hash(potatoes: [{ name: 'Ac Belmont' }, { name: 'Eramosa' }])
55
+ end
56
+ end
57
+
58
+ it 'can be embeded in array - complex' do
59
+ schema = ParametersSchema::Schema.new do
60
+ param :potatoes, array: true do
61
+ param :quantity, type: Fixnum
62
+ param :description do
63
+ param :name
64
+ param :local, type: :boolean
65
+ end
66
+ end
67
+ end
68
+
69
+ potatoes = [
70
+ {
71
+ quantity: 10,
72
+ description: {
73
+ name: 'Eramosa',
74
+ local: true
75
+ }
76
+ },
77
+ {
78
+ quantity: 1000,
79
+ description: {
80
+ name: 'Eramosa II',
81
+ local: false
82
+ }
83
+ }
84
+ ]
85
+
86
+ schema
87
+ .validate!(potatoes: potatoes)
88
+ .must_equal_hash(potatoes: potatoes)
89
+ end
90
+ end
@@ -0,0 +1,74 @@
1
+ require 'minitest/autorun'
2
+ require 'parameters_schema'
3
+ require_relative 'helpers'
4
+
5
+ describe 'Required' do
6
+ before do
7
+ ParametersSchema::Options.reset_defaults
8
+ end
9
+
10
+ it 'is required by default' do
11
+ Proc.new do
12
+ ParametersSchema::Schema.new do
13
+ param :potatoe
14
+ end.validate!({})
15
+ end
16
+ .must_raise(ParametersSchema::InvalidParameters)
17
+ .errors.must_equal_hash(potatoe: ParametersSchema::ErrorCode::MISSING)
18
+ end
19
+
20
+ it 'can be explicitly stated as required' do
21
+ Proc.new do
22
+ ParametersSchema::Schema.new do
23
+ param :potatoe, required: true
24
+ end.validate!({})
25
+ end
26
+ .must_raise(ParametersSchema::InvalidParameters)
27
+ .errors.must_equal_hash(potatoe: ParametersSchema::ErrorCode::MISSING)
28
+ end
29
+
30
+ it 'can be set to be not required' do
31
+ ParametersSchema::Schema.new do
32
+ param :potatoe, required: false
33
+ end
34
+ .validate!({})
35
+ .must_equal_hash({})
36
+ end
37
+
38
+ it 'applies to object params - validation successful' do
39
+ ParametersSchema::Schema.new do
40
+ param :potatoe do
41
+ param :name
42
+ param :type, required: false
43
+ end
44
+ end
45
+ .validate!(potatoe: { name: 'Eramosa' })
46
+ .must_equal_hash(potatoe: { name: 'Eramosa' })
47
+ end
48
+
49
+ it 'applies to object params - validation failed on name' do
50
+ Proc.new do
51
+ ParametersSchema::Schema.new do
52
+ param :potatoe do
53
+ param :name
54
+ param :type, required: false
55
+ end
56
+ end.validate!(potatoe: {})
57
+ end
58
+ .must_raise(ParametersSchema::InvalidParameters)
59
+ .errors.must_equal_hash(potatoe: { name: ParametersSchema::ErrorCode::MISSING })
60
+ end
61
+
62
+ it 'applies to object params - validation failed on potatoe' do
63
+ Proc.new do
64
+ ParametersSchema::Schema.new do
65
+ param :potatoe do
66
+ param :name
67
+ param :type, required: false
68
+ end
69
+ end.validate!({})
70
+ end
71
+ .must_raise(ParametersSchema::InvalidParameters)
72
+ .errors.must_equal_hash(potatoe: ParametersSchema::ErrorCode::MISSING)
73
+ end
74
+ end