parameters_schema 0.42

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.
@@ -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