chef-attribute-validator 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +20 -0
- data/CHANGES +4 -0
- data/Gemfile +2 -0
- data/LICENSE +27 -0
- data/README.md +109 -0
- data/Rakefile +27 -0
- data/chef-attribute-validator.gemspec +25 -0
- data/lib/chef-attribute-validator.rb +52 -0
- data/lib/chef-attribute-validator/attribute_set.rb +90 -0
- data/lib/chef-attribute-validator/check.rb +56 -0
- data/lib/chef-attribute-validator/checks/looks_like.rb +52 -0
- data/lib/chef-attribute-validator/checks/max_children.rb +37 -0
- data/lib/chef-attribute-validator/checks/min_children.rb +37 -0
- data/lib/chef-attribute-validator/checks/regex.rb +31 -0
- data/lib/chef-attribute-validator/checks/required.rb +42 -0
- data/lib/chef-attribute-validator/checks/type.rb +48 -0
- data/lib/chef-attribute-validator/rule.rb +54 -0
- data/lib/chef-attribute-validator/version.rb +7 -0
- data/lib/chef-attribute-validator/violation.rb +17 -0
- data/test/fixtures/attr_set.rb +10 -0
- data/test/fixtures/check_child_count.rb +104 -0
- data/test/fixtures/check_looks_like_arg_ip.rb +6 -0
- data/test/fixtures/check_looks_like_arg_regex.rb +6 -0
- data/test/fixtures/check_looks_like_arg_url.rb +6 -0
- data/test/fixtures/check_looks_like_arg_your_mom.rb +6 -0
- data/test/fixtures/check_looks_like_ip.rb +57 -0
- data/test/fixtures/check_looks_like_url.rb +39 -0
- data/test/fixtures/check_regex_assorted.rb +42 -0
- data/test/fixtures/check_regex_literal.rb +5 -0
- data/test/fixtures/check_regex_nil.rb +5 -0
- data/test/fixtures/check_regex_object.rb +5 -0
- data/test/fixtures/check_regex_string.rb +5 -0
- data/test/fixtures/check_required_assorted.rb +82 -0
- data/test/fixtures/check_required_false.rb +5 -0
- data/test/fixtures/check_required_true.rb +5 -0
- data/test/fixtures/check_required_zero.rb +5 -0
- data/test/fixtures/check_type.rb +270 -0
- data/test/fixtures/rules_empty.rb +2 -0
- data/test/fixtures/rules_missing_path.rb +1 -0
- data/test/fixtures/rules_no_check.rb +1 -0
- data/test/fixtures/rules_type_and_min_children.rb +3 -0
- data/test/fixtures/rules_type_check.rb +2 -0
- data/test/unit/attr_set_spec.rb +55 -0
- data/test/unit/check_child_count_spec.rb +109 -0
- data/test/unit/check_looks_like_spec.rb +106 -0
- data/test/unit/check_regex_spec.rb +62 -0
- data/test/unit/check_required_spec.rb +106 -0
- data/test/unit/check_type_spec.rb +191 -0
- data/test/unit/rule_parse_spec.rb +93 -0
- data/test/unit/spec_helper.rb +18 -0
- metadata +170 -0
@@ -0,0 +1 @@
|
|
1
|
+
default['attribute-validator']['rules']['test-missing-path']['enabled'] = true
|
@@ -0,0 +1 @@
|
|
1
|
+
default['attribute-validator']['rules']['test-no-check-rule']['path'] = '/*'
|
@@ -0,0 +1,3 @@
|
|
1
|
+
default['attribute-validator']['rules']['test-type-and-min-children-rule']['path'] = '/*'
|
2
|
+
default['attribute-validator']['rules']['test-type-and-min-children-rule']['type'] = 'array'
|
3
|
+
default['attribute-validator']['rules']['test-type-and-min-children-rule']['min_children'] = 1
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
|
3
|
+
describe Chef::Attribute::Validator::AttributeSet do
|
4
|
+
|
5
|
+
let(:node) { CAVHelper.load_fixture_attributes('attr_set') }
|
6
|
+
|
7
|
+
describe "non-wildcard, non-array slashpath access" do
|
8
|
+
context "when the element exists" do
|
9
|
+
it "should be able to run /one" do
|
10
|
+
expect { Chef::Attribute::Validator::AttributeSet.new(node, '/one') }.not_to raise_error
|
11
|
+
end
|
12
|
+
let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/one') }
|
13
|
+
it "should be able to find /one" do
|
14
|
+
expect(ats.size).to eq 1
|
15
|
+
expect(ats.has_key?('/one')).to be_true
|
16
|
+
expect(ats['/one']).to eq 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when the element does not exist" do
|
21
|
+
it "should be able to run /nope" do
|
22
|
+
expect { Chef::Attribute::Validator::AttributeSet.new(node, '/nope') }.not_to raise_error
|
23
|
+
end
|
24
|
+
let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/nope') }
|
25
|
+
it "should not be able to find /nope" do
|
26
|
+
expect(ats.size).to eq 0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "non-wildcard, array slashpath access" do
|
32
|
+
context "when the element exists" do
|
33
|
+
it "should be able to run /cats/1" do
|
34
|
+
expect { Chef::Attribute::Validator::AttributeSet.new(node, '/cats/1') }.not_to raise_error
|
35
|
+
end
|
36
|
+
let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/cats/1') }
|
37
|
+
it "should be able to find /cats/1" do
|
38
|
+
expect(ats.size).to eq 1
|
39
|
+
expect(ats.has_key?('/cats/1')).to be_true
|
40
|
+
expect(ats['/cats/1']).to eq 'tabby'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when the element does not exist" do
|
45
|
+
it "should be able to run /cats/23" do
|
46
|
+
expect { Chef::Attribute::Validator::AttributeSet.new(node, '/cats/23') }.not_to raise_error
|
47
|
+
end
|
48
|
+
let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/cats/23') }
|
49
|
+
it "should not be able to find /cats/23" do
|
50
|
+
expect(ats.size).to eq 0
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
|
3
|
+
# Verify that the 'type' check works correctly
|
4
|
+
|
5
|
+
|
6
|
+
describe "'min_children' check" do
|
7
|
+
|
8
|
+
let(:node) { CAVHelper.load_fixture_attributes('check_child_count') }
|
9
|
+
let(:av) { Chef::Attribute::Validator.new(node) }
|
10
|
+
|
11
|
+
it "should be present in the Check registry" do
|
12
|
+
expect(Chef::Attribute::Validator::Check.list_check_types).to include('min_children')
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should violate on nil" do
|
16
|
+
expect(av.validate_rule('min-nil')).not_to be_empty
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should violate on string" do
|
20
|
+
expect(av.validate_rule('min-string')).not_to be_empty
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when examining an array" do
|
24
|
+
it "should not violate when min is 0 and array is empty" do
|
25
|
+
expect(av.validate_rule('min-array-empty-zero')).to be_empty
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should violate when min is 1 and array is empty" do
|
29
|
+
expect(av.validate_rule('min-array-empty-one')).not_to be_empty
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should violate when min is 2 and array is 1" do
|
33
|
+
expect(av.validate_rule('min-array-one-two')).not_to be_empty
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when examining a hash" do
|
38
|
+
it "should not violate when min is 0 and hash is empty" do
|
39
|
+
expect(av.validate_rule('min-hash-empty-zero')).to be_empty
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should violate when min is 1 and hash is empty" do
|
43
|
+
expect(av.validate_rule('min-hash-empty-one')).not_to be_empty
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should violate when min is 2 and hash is 1" do
|
47
|
+
expect(av.validate_rule('min-hash-one-two')).not_to be_empty
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "'max_children' check" do
|
54
|
+
|
55
|
+
let(:node) { CAVHelper.load_fixture_attributes('check_child_count') }
|
56
|
+
let(:av) { Chef::Attribute::Validator.new(node) }
|
57
|
+
|
58
|
+
it "should be present in the Check registry" do
|
59
|
+
expect(Chef::Attribute::Validator::Check.list_check_types).to include('max_children')
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should violate on nil" do
|
63
|
+
expect(av.validate_rule('max-nil')).not_to be_empty
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should violate on string" do
|
67
|
+
expect(av.validate_rule('max-string')).not_to be_empty
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when examining an array" do
|
71
|
+
it "should not violate when max is 0 and array is empty" do
|
72
|
+
expect(av.validate_rule('max-array-empty-zero')).to be_empty
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should violate when max is 0 and array is 1" do
|
76
|
+
expect(av.validate_rule('max-array-zero-one')).not_to be_empty
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should violate when max is 1 and array is 2" do
|
80
|
+
expect(av.validate_rule('max-array-one-two')).not_to be_empty
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should not violate when max is 2 and array is 2" do
|
84
|
+
expect(av.validate_rule('max-array-two-two')).to be_empty
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
context "when examining a hash" do
|
90
|
+
it "should not violate when max is 0 and hash is empty" do
|
91
|
+
expect(av.validate_rule('max-hash-empty-zero')).to be_empty
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should violate when max is 0 and hash is one" do
|
95
|
+
expect(av.validate_rule('max-hash-zero-one')).not_to be_empty
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should violate when max is 1 and hash is 2" do
|
99
|
+
expect(av.validate_rule('max-hash-one-two')).not_to be_empty
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should not violate when max is 2 and hash is 2" do
|
103
|
+
expect(av.validate_rule('max-hash-two-two')).to be_empty
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
|
3
|
+
# Verify that the 'looks_like' check works correctly
|
4
|
+
|
5
|
+
|
6
|
+
describe "'looks_like' check" do
|
7
|
+
|
8
|
+
describe "check registry" do
|
9
|
+
it "should be present in the Check registry" do
|
10
|
+
expect(Chef::Attribute::Validator::Check.list_check_types).to include('looks_like')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "check_arg checks" do
|
15
|
+
it "should accept 'ip'" do
|
16
|
+
node = CAVHelper.load_fixture_attributes('check_looks_like_arg_ip')
|
17
|
+
expect { Chef::Attribute::Validator.new(node) }.not_to raise_error
|
18
|
+
end
|
19
|
+
it "should accept 'url'" do
|
20
|
+
node = CAVHelper.load_fixture_attributes('check_looks_like_arg_url')
|
21
|
+
expect { Chef::Attribute::Validator.new(node) }.not_to raise_error
|
22
|
+
end
|
23
|
+
it "should reject 'your mom'" do
|
24
|
+
node = CAVHelper.load_fixture_attributes('check_looks_like_arg_your_mom')
|
25
|
+
expect { Chef::Attribute::Validator.new(node) }.to raise_error
|
26
|
+
end
|
27
|
+
it "should reject a regex" do
|
28
|
+
node = CAVHelper.load_fixture_attributes('check_looks_like_arg_regex')
|
29
|
+
expect { Chef::Attribute::Validator.new(node) }.to raise_error
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when the mode is 'ip'" do
|
34
|
+
let(:node) { CAVHelper.load_fixture_attributes('check_looks_like_ip') }
|
35
|
+
let(:av) { Chef::Attribute::Validator.new(node) }
|
36
|
+
|
37
|
+
it "should not violate on missing" do
|
38
|
+
expect(av.validate_rule('ip-missing')).to be_empty
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should not violate on nil" do
|
42
|
+
expect(av.validate_rule('ip-nil')).to be_empty
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should violate on 1234.123.1.1" do
|
46
|
+
expect(av.validate_rule('ip-malformed')).not_to be_empty
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should violate on 300.300.300.1" do
|
50
|
+
expect(av.validate_rule('ip-deranged')).not_to be_empty
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should violate on 123.123.123" do
|
54
|
+
expect(av.validate_rule('ip-3not4')).not_to be_empty
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should not violate on 1.1.1.1" do
|
58
|
+
expect(av.validate_rule('ip-allones')).to be_empty
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should not violate on 1.1.1.1/24" do
|
62
|
+
expect(av.validate_rule('ip-slash24')).to be_empty
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should not violate on 255.255.255.255" do
|
66
|
+
expect(av.validate_rule('ip-merryxmas')).to be_empty
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should not violate on ::" do
|
70
|
+
expect(av.validate_rule('ip-emptyv6')).to be_empty
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "when the mode is 'url'" do
|
75
|
+
let(:node) { CAVHelper.load_fixture_attributes('check_looks_like_url') }
|
76
|
+
let(:av) { Chef::Attribute::Validator.new(node) }
|
77
|
+
|
78
|
+
it "should not violate on missing" do
|
79
|
+
expect(av.validate_rule('url-missing')).to be_empty
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should not violate on nil" do
|
83
|
+
expect(av.validate_rule('url-nil')).to be_empty
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not violate on 'http://wwwwwwww.jodi.org'" do
|
87
|
+
expect(av.validate_rule('url-http-basic')).to be_empty
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should not violate on 'http://example.com/'" do
|
91
|
+
expect(av.validate_rule('url-http-trailing-slash')).to be_empty
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should not violate on 'http://example.com:8080/'" do
|
95
|
+
expect(av.validate_rule('url-http-port')).to be_empty
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should not violate on 'http://localhost'" do
|
99
|
+
expect(av.validate_rule('url-http-localhost')).to be_empty
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
|
106
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
|
3
|
+
# Verify that the 'regex' check works correctly
|
4
|
+
|
5
|
+
|
6
|
+
describe "'regex' check" do
|
7
|
+
|
8
|
+
describe "check registry" do
|
9
|
+
it "should be present in the Check registry" do
|
10
|
+
expect(Chef::Attribute::Validator::Check.list_check_types).to include('regex')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "check_arg checks" do
|
15
|
+
it "should accept a // literal regex" do
|
16
|
+
node = CAVHelper.load_fixture_attributes('check_regex_literal')
|
17
|
+
expect { Chef::Attribute::Validator.new(node) }.not_to raise_error
|
18
|
+
end
|
19
|
+
it "should accept a Regexp object" do
|
20
|
+
node = CAVHelper.load_fixture_attributes('check_regex_object')
|
21
|
+
expect { Chef::Attribute::Validator.new(node) }.not_to raise_error
|
22
|
+
end
|
23
|
+
it "should reject a string" do
|
24
|
+
node = CAVHelper.load_fixture_attributes('check_regex_string')
|
25
|
+
expect { Chef::Attribute::Validator.new(node) }.to raise_error
|
26
|
+
end
|
27
|
+
it "should reject a nil regex" do
|
28
|
+
node = CAVHelper.load_fixture_attributes('check_regex_nil')
|
29
|
+
expect { Chef::Attribute::Validator.new(node) }.to raise_error
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "assorted regexes" do
|
34
|
+
let(:node) { CAVHelper.load_fixture_attributes('check_regex_assorted') }
|
35
|
+
let(:av) { Chef::Attribute::Validator.new(node) }
|
36
|
+
|
37
|
+
it "/^$/ should not violate on an empty string" do
|
38
|
+
expect(av.validate_rule('empty-empty')).to be_empty
|
39
|
+
end
|
40
|
+
|
41
|
+
it "/foo/ should not violate on foo" do
|
42
|
+
expect(av.validate_rule('foo-foo')).to be_empty
|
43
|
+
end
|
44
|
+
|
45
|
+
it "/foo/ should not violate on food" do
|
46
|
+
expect(av.validate_rule('foo-food')).to be_empty
|
47
|
+
end
|
48
|
+
|
49
|
+
it "/foo/ should violate on victuals" do
|
50
|
+
expect(av.validate_rule('foo-victuals')).not_to be_empty
|
51
|
+
end
|
52
|
+
|
53
|
+
it "/^(?!foo)/ should not violate on bar" do
|
54
|
+
expect(av.validate_rule('not-foo-bar')).to be_empty
|
55
|
+
end
|
56
|
+
|
57
|
+
it "/^(?!foo)/ should violate on foo" do
|
58
|
+
expect(av.validate_rule('not-foo-foo')).not_to be_empty
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
|
3
|
+
# Verify that the 'required' check works correctly
|
4
|
+
|
5
|
+
describe "'required' check" do
|
6
|
+
|
7
|
+
describe "check registry" do
|
8
|
+
it "should be present in the Check registry" do
|
9
|
+
expect(Chef::Attribute::Validator::Check.list_check_types).to include('required')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "check_arg checks" do
|
14
|
+
it "should accept true" do
|
15
|
+
node = CAVHelper.load_fixture_attributes('check_required_true')
|
16
|
+
expect { Chef::Attribute::Validator.new(node) }.not_to raise_error
|
17
|
+
end
|
18
|
+
it "should accept false" do
|
19
|
+
node = CAVHelper.load_fixture_attributes('check_required_false')
|
20
|
+
expect { Chef::Attribute::Validator.new(node) }.not_to raise_error
|
21
|
+
end
|
22
|
+
it "should reject 0" do
|
23
|
+
node = CAVHelper.load_fixture_attributes('check_required_zero')
|
24
|
+
expect { Chef::Attribute::Validator.new(node) }.to raise_error
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when required, but the attribute is missing" do
|
29
|
+
let(:node) { CAVHelper.load_fixture_attributes('check_required_assorted') }
|
30
|
+
let(:av) { Chef::Attribute::Validator.new(node) }
|
31
|
+
|
32
|
+
it "should violate when the attribute is missing, shallow" do
|
33
|
+
expect(av.validate_rule('missing-shallow')).not_to be_empty
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should violate when the attribute is missing, deep" do
|
37
|
+
expect(av.validate_rule('missing-deep')).not_to be_empty
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when required, but the value is missing" do
|
42
|
+
let(:node) { CAVHelper.load_fixture_attributes('check_required_assorted') }
|
43
|
+
let(:av) { Chef::Attribute::Validator.new(node) }
|
44
|
+
|
45
|
+
it "should violate when the value is nil" do
|
46
|
+
expect(av.validate_rule('value-nil')).not_to be_empty
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should violate when the value is an empty string" do
|
50
|
+
expect(av.validate_rule('value-empty-string')).not_to be_empty
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should violate when the value is an empty array" do
|
54
|
+
expect(av.validate_rule('value-empty-array')).not_to be_empty
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should violate when the value is an empty hash" do
|
58
|
+
expect(av.validate_rule('value-empty-hash')).not_to be_empty
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when required, and a value is present" do
|
63
|
+
let(:node) { CAVHelper.load_fixture_attributes('check_required_assorted') }
|
64
|
+
let(:av) { Chef::Attribute::Validator.new(node) }
|
65
|
+
|
66
|
+
it "should not violate when the value is a string " do
|
67
|
+
expect(av.validate_rule('value-present-string')).to be_empty
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should not violate when the value is false " do
|
71
|
+
expect(av.validate_rule('value-present-false')).to be_empty
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should not violate when the value is zero " do
|
75
|
+
expect(av.validate_rule('value-present-zero')).to be_empty
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should not violate when the value is a non-empty array " do
|
79
|
+
expect(av.validate_rule('value-present-array')).to be_empty
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should not violate when the value is a non-empty hash" do
|
83
|
+
expect(av.validate_rule('value-present-hash')).to be_empty
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "when not required, but the value is present" do
|
88
|
+
let(:node) { CAVHelper.load_fixture_attributes('check_required_assorted') }
|
89
|
+
let(:av) { Chef::Attribute::Validator.new(node) }
|
90
|
+
|
91
|
+
it "should not violate when the value is a string" do
|
92
|
+
expect(av.validate_rule('optional-present-string')).to be_empty
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "when not required, but the attribute is missing" do
|
97
|
+
let(:node) { CAVHelper.load_fixture_attributes('check_required_assorted') }
|
98
|
+
let(:av) { Chef::Attribute::Validator.new(node) }
|
99
|
+
|
100
|
+
it "should not violate when the attribute is missing" do
|
101
|
+
expect(av.validate_rule('optional-missing')).to be_empty
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
end
|