attestor 0.0.1
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 +7 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +9 -0
- data/.metrics +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +10 -0
- data/.yardopts +3 -0
- data/Gemfile +5 -0
- data/Guardfile +15 -0
- data/LICENSE +21 -0
- data/README.md +308 -0
- data/Rakefile +22 -0
- data/attestor.gemspec +24 -0
- data/config/metrics/STYLEGUIDE +230 -0
- data/config/metrics/cane.yml +5 -0
- data/config/metrics/churn.yml +6 -0
- data/config/metrics/flay.yml +2 -0
- data/config/metrics/metric_fu.yml +15 -0
- data/config/metrics/reek.yml +1 -0
- data/config/metrics/roodi.yml +24 -0
- data/config/metrics/rubocop.yml +75 -0
- data/config/metrics/saikuro.yml +3 -0
- data/config/metrics/simplecov.yml +6 -0
- data/config/metrics/yardstick.yml +37 -0
- data/lib/attestor/invalid_error.rb +44 -0
- data/lib/attestor/policy/and.rb +36 -0
- data/lib/attestor/policy/factory.rb +88 -0
- data/lib/attestor/policy/negator.rb +53 -0
- data/lib/attestor/policy/node.rb +58 -0
- data/lib/attestor/policy/not.rb +48 -0
- data/lib/attestor/policy/or.rb +36 -0
- data/lib/attestor/policy/xor.rb +36 -0
- data/lib/attestor/policy.rb +121 -0
- data/lib/attestor/validations/collection.rb +73 -0
- data/lib/attestor/validations/item.rb +87 -0
- data/lib/attestor/validations/message.rb +55 -0
- data/lib/attestor/validations.rb +81 -0
- data/lib/attestor/version.rb +9 -0
- data/lib/attestor.rb +26 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/policies.rb +49 -0
- data/spec/tests/invalid_error_spec.rb +57 -0
- data/spec/tests/policy/and_spec.rb +40 -0
- data/spec/tests/policy/factory_spec.rb +100 -0
- data/spec/tests/policy/negator_spec.rb +57 -0
- data/spec/tests/policy/node_spec.rb +44 -0
- data/spec/tests/policy/not_spec.rb +40 -0
- data/spec/tests/policy/or_spec.rb +40 -0
- data/spec/tests/policy/xor_spec.rb +48 -0
- data/spec/tests/policy_spec.rb +111 -0
- data/spec/tests/validations/collection_spec.rb +100 -0
- data/spec/tests/validations/item_spec.rb +153 -0
- data/spec/tests/validations/message_spec.rb +71 -0
- data/spec/tests/validations_spec.rb +126 -0
- metadata +143 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# describe #valid_policy and #invalid_policy builders
|
4
|
+
# also describes shared examples for all policies
|
5
|
+
require "support/policies"
|
6
|
+
|
7
|
+
describe Attestor::Policy::Not do
|
8
|
+
|
9
|
+
subject { described_class.new item }
|
10
|
+
|
11
|
+
describe ".new" do
|
12
|
+
|
13
|
+
let(:item) { valid_policy }
|
14
|
+
|
15
|
+
it_behaves_like "creating a node"
|
16
|
+
it_behaves_like "creating an immutable object"
|
17
|
+
|
18
|
+
end # context
|
19
|
+
|
20
|
+
describe "#validate" do
|
21
|
+
|
22
|
+
context "when a part is invalid" do
|
23
|
+
|
24
|
+
let(:item) { invalid_policy }
|
25
|
+
|
26
|
+
it_behaves_like "passing validation"
|
27
|
+
|
28
|
+
end # context
|
29
|
+
|
30
|
+
context "when a part is valid" do
|
31
|
+
|
32
|
+
let(:item) { valid_policy }
|
33
|
+
|
34
|
+
it_behaves_like "failing validation"
|
35
|
+
|
36
|
+
end # context
|
37
|
+
|
38
|
+
end # describe #validate
|
39
|
+
|
40
|
+
end # describe Policy::Base::Not
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# describe #valid_policy and #invalid_policy builders
|
4
|
+
# also describes shared examples for all policies
|
5
|
+
require "support/policies"
|
6
|
+
|
7
|
+
describe Attestor::Policy::Or do
|
8
|
+
|
9
|
+
subject { described_class.new items }
|
10
|
+
|
11
|
+
describe ".new" do
|
12
|
+
|
13
|
+
let(:items) { [valid_policy] }
|
14
|
+
|
15
|
+
it_behaves_like "creating a node"
|
16
|
+
it_behaves_like "creating an immutable object"
|
17
|
+
|
18
|
+
end # context
|
19
|
+
|
20
|
+
describe "#validate" do
|
21
|
+
|
22
|
+
context "when valid part exists" do
|
23
|
+
|
24
|
+
let(:items) { [valid_policy, valid_policy, invalid_policy] }
|
25
|
+
|
26
|
+
it_behaves_like "passing validation"
|
27
|
+
|
28
|
+
end # context
|
29
|
+
|
30
|
+
context "when all parts are invalid" do
|
31
|
+
|
32
|
+
let(:items) { 3.times.map { invalid_policy } }
|
33
|
+
|
34
|
+
it_behaves_like "failing validation"
|
35
|
+
|
36
|
+
end # context
|
37
|
+
|
38
|
+
end # describe #validate
|
39
|
+
|
40
|
+
end # describe Policy::Base::Not
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# describe #valid_policy and #invalid_policy builders
|
4
|
+
# also describes shared examples for all policies
|
5
|
+
require "support/policies"
|
6
|
+
|
7
|
+
describe Attestor::Policy::Xor do
|
8
|
+
|
9
|
+
subject { described_class.new items }
|
10
|
+
|
11
|
+
describe ".new" do
|
12
|
+
|
13
|
+
let(:items) { [valid_policy] }
|
14
|
+
|
15
|
+
it_behaves_like "creating a node"
|
16
|
+
it_behaves_like "creating an immutable object"
|
17
|
+
|
18
|
+
end # context
|
19
|
+
|
20
|
+
describe "#validate" do
|
21
|
+
|
22
|
+
context "when both valid and invalid parts exist" do
|
23
|
+
|
24
|
+
let(:items) { [valid_policy, valid_policy, invalid_policy] }
|
25
|
+
|
26
|
+
it_behaves_like "passing validation"
|
27
|
+
|
28
|
+
end # context
|
29
|
+
|
30
|
+
context "when all parts are valid" do
|
31
|
+
|
32
|
+
let(:items) { 3.times.map { valid_policy } }
|
33
|
+
|
34
|
+
it_behaves_like "failing validation"
|
35
|
+
|
36
|
+
end # context
|
37
|
+
|
38
|
+
context "when all parts are invalid" do
|
39
|
+
|
40
|
+
let(:items) { 3.times.map { invalid_policy } }
|
41
|
+
|
42
|
+
it_behaves_like "failing validation"
|
43
|
+
|
44
|
+
end # context
|
45
|
+
|
46
|
+
end # describe #validate
|
47
|
+
|
48
|
+
end # describe Policy::Base::Not
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Attestor::Policy do
|
4
|
+
|
5
|
+
let(:factory) { Attestor::Policy::Factory }
|
6
|
+
let(:validator) { Attestor::Validations }
|
7
|
+
let(:invalid) { Attestor::InvalidError.new subject, [] }
|
8
|
+
let(:others) { 2.times { double } }
|
9
|
+
|
10
|
+
let(:test_class) { Class.new.send(:include, described_class) }
|
11
|
+
before { Test = test_class }
|
12
|
+
after { Object.send :remove_const, :Test }
|
13
|
+
subject { test_class.new }
|
14
|
+
|
15
|
+
it "is a factory" do
|
16
|
+
expect(test_class).to be_kind_of factory
|
17
|
+
end
|
18
|
+
|
19
|
+
describe ".new" do
|
20
|
+
|
21
|
+
it "creates a validator" do
|
22
|
+
expect(subject).to be_kind_of validator
|
23
|
+
end
|
24
|
+
|
25
|
+
end # describe .new
|
26
|
+
|
27
|
+
describe "#valid?" do
|
28
|
+
|
29
|
+
context "when #validate method fails" do
|
30
|
+
|
31
|
+
before { allow(subject).to receive(:validate) { fail invalid } }
|
32
|
+
|
33
|
+
it "returns false" do
|
34
|
+
expect(subject.valid?).to eq false
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when #validate method passes" do
|
40
|
+
|
41
|
+
before { allow(subject).to receive(:validate) { nil } }
|
42
|
+
|
43
|
+
it "returns true" do
|
44
|
+
expect(subject.valid?).to eq true
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end # describe #valid?
|
50
|
+
|
51
|
+
describe "#invalid?" do
|
52
|
+
|
53
|
+
context "when #validate method fails" do
|
54
|
+
|
55
|
+
before { allow(subject).to receive(:validate) { fail invalid } }
|
56
|
+
|
57
|
+
it "returns true" do
|
58
|
+
expect(subject.invalid?).to eq true
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when #validate method passes" do
|
64
|
+
|
65
|
+
before { allow(subject).to receive(:validate) { nil } }
|
66
|
+
|
67
|
+
it "returns false" do
|
68
|
+
expect(subject.invalid?).to eq false
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end # describe #invalid?
|
74
|
+
|
75
|
+
describe "#and" do
|
76
|
+
|
77
|
+
it "calls .and class factory method with self" do
|
78
|
+
expect(test_class).to receive(:and).with(subject, *others)
|
79
|
+
subject.and(*others)
|
80
|
+
end
|
81
|
+
|
82
|
+
end # describe #and
|
83
|
+
|
84
|
+
describe "#or" do
|
85
|
+
|
86
|
+
it "calls .or class factory method with self" do
|
87
|
+
expect(test_class).to receive(:or).with(subject, *others)
|
88
|
+
subject.or(*others)
|
89
|
+
end
|
90
|
+
|
91
|
+
end # describe #or
|
92
|
+
|
93
|
+
describe "#xor" do
|
94
|
+
|
95
|
+
it "calls .xor class factory method with self" do
|
96
|
+
expect(test_class).to receive(:xor).with(subject, *others)
|
97
|
+
subject.xor(*others)
|
98
|
+
end
|
99
|
+
|
100
|
+
end # describe #xor
|
101
|
+
|
102
|
+
describe "#not" do
|
103
|
+
|
104
|
+
it "calls .not class factory method with self" do
|
105
|
+
expect(test_class).to receive(:not).with(subject)
|
106
|
+
subject.not
|
107
|
+
end
|
108
|
+
|
109
|
+
end # describe #not
|
110
|
+
|
111
|
+
end # describe Attestor::Policy
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Attestor::Validations::Collection do
|
4
|
+
|
5
|
+
let(:item_class) { Attestor::Validations::Item }
|
6
|
+
|
7
|
+
describe ".new" do
|
8
|
+
|
9
|
+
it "creates a collection" do
|
10
|
+
expect(subject).to be_kind_of Enumerable
|
11
|
+
end
|
12
|
+
|
13
|
+
it "creates an immutable object" do
|
14
|
+
expect(subject).to be_frozen
|
15
|
+
end
|
16
|
+
|
17
|
+
end # .new
|
18
|
+
|
19
|
+
describe "#each" do
|
20
|
+
|
21
|
+
it "returns an enumerator" do
|
22
|
+
expect(subject.each).to be_kind_of Enumerator
|
23
|
+
end
|
24
|
+
|
25
|
+
it "iterates trough the unique item names" do
|
26
|
+
items = %w(foo bar foo).map(&item_class.method(:new))
|
27
|
+
subject = described_class.new items
|
28
|
+
|
29
|
+
expect(subject.to_a).to match_array %i(foo bar)
|
30
|
+
end
|
31
|
+
|
32
|
+
end # describe #each
|
33
|
+
|
34
|
+
describe "#add" do
|
35
|
+
|
36
|
+
context "without options" do
|
37
|
+
|
38
|
+
let(:result) { subject.add("foo") }
|
39
|
+
|
40
|
+
it "returns the collection" do
|
41
|
+
expect(result).to be_kind_of described_class
|
42
|
+
end
|
43
|
+
|
44
|
+
it "adds item to the collection" do
|
45
|
+
item = result.first
|
46
|
+
expect(item).to eq :foo
|
47
|
+
end
|
48
|
+
|
49
|
+
it "preserves existing items" do
|
50
|
+
expect(result.add(:bar).to_a).to contain_exactly :foo, :bar
|
51
|
+
end
|
52
|
+
|
53
|
+
end # context
|
54
|
+
|
55
|
+
context "with options" do
|
56
|
+
|
57
|
+
let(:result) { subject.add "foo", only: [:foo] }
|
58
|
+
|
59
|
+
it "adds item to the collection" do
|
60
|
+
expect(result.to_a).to eq [:foo]
|
61
|
+
expect(result.set(:foo).to_a).to eq [:foo]
|
62
|
+
expect(result.set(:all).to_a).to eq []
|
63
|
+
end
|
64
|
+
|
65
|
+
end # context
|
66
|
+
|
67
|
+
context "existing item" do
|
68
|
+
|
69
|
+
subject { described_class.new.add "foo" }
|
70
|
+
|
71
|
+
it "returns itself" do
|
72
|
+
expect(subject.add "foo").to eq subject
|
73
|
+
end
|
74
|
+
|
75
|
+
end # context
|
76
|
+
|
77
|
+
end # describe #add
|
78
|
+
|
79
|
+
describe "#context" do
|
80
|
+
|
81
|
+
subject do
|
82
|
+
described_class.new
|
83
|
+
.add("foo", only: %w(cad cam))
|
84
|
+
.add("bar", except: %w(cad))
|
85
|
+
.add("baz", except: %w(cam))
|
86
|
+
end
|
87
|
+
|
88
|
+
it "returns a collection" do
|
89
|
+
expect(subject.set "all").to be_kind_of described_class
|
90
|
+
end
|
91
|
+
|
92
|
+
it "returns a set of items used in given context" do
|
93
|
+
expect(subject.set("cad").to_a).to contain_exactly :foo, :baz
|
94
|
+
expect(subject.set("cam").to_a).to contain_exactly :foo, :bar
|
95
|
+
expect(subject.set("all").to_a).to contain_exactly :bar, :baz
|
96
|
+
end
|
97
|
+
|
98
|
+
end # describe #context
|
99
|
+
|
100
|
+
end # describe Attestor::Collection
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Attestor::Validations::Item do
|
4
|
+
|
5
|
+
subject { described_class.new "foo" }
|
6
|
+
|
7
|
+
describe ".new" do
|
8
|
+
|
9
|
+
it "is immutable" do
|
10
|
+
expect(subject).to be_frozen
|
11
|
+
end
|
12
|
+
|
13
|
+
it "accepts item option :except" do
|
14
|
+
expect { described_class.new "foo", except: :bar }.not_to raise_error
|
15
|
+
end
|
16
|
+
|
17
|
+
it "accepts array option :except" do
|
18
|
+
expect { described_class.new "foo", except: %w(bar) }.not_to raise_error
|
19
|
+
end
|
20
|
+
|
21
|
+
it "ignores repetitive :except items" do
|
22
|
+
expect(described_class.new "foo", except: %i(bar bar))
|
23
|
+
.to eq(described_class.new "foo", except: %i(bar))
|
24
|
+
end
|
25
|
+
|
26
|
+
it "accepts item option :only" do
|
27
|
+
expect { described_class.new "foo", only: :bar }.not_to raise_error
|
28
|
+
end
|
29
|
+
|
30
|
+
it "accepts array option :only" do
|
31
|
+
expect { described_class.new "foo", only: %w(bar) }.not_to raise_error
|
32
|
+
end
|
33
|
+
|
34
|
+
it "ignores repetitive :only items" do
|
35
|
+
expect(described_class.new "foo", only: %i(bar bar))
|
36
|
+
.to eq(described_class.new "foo", only: %i(bar))
|
37
|
+
end
|
38
|
+
|
39
|
+
end # describe .new
|
40
|
+
|
41
|
+
describe ".name" do
|
42
|
+
|
43
|
+
it "is initialized as a symbol" do
|
44
|
+
expect(subject.name).to eq :foo
|
45
|
+
end
|
46
|
+
|
47
|
+
end # describe .name
|
48
|
+
|
49
|
+
describe "#==" do
|
50
|
+
|
51
|
+
subject { described_class.new :foo, except: [:foo], only: %i(bar) }
|
52
|
+
|
53
|
+
context "item with the same name and options" do
|
54
|
+
|
55
|
+
let(:other) { described_class.new :foo, except: %i(foo), only: %i(bar) }
|
56
|
+
|
57
|
+
it "returns true" do
|
58
|
+
expect(subject == other).to eq true
|
59
|
+
expect(subject).to eq other
|
60
|
+
end
|
61
|
+
|
62
|
+
end # context
|
63
|
+
|
64
|
+
context "item with another name" do
|
65
|
+
|
66
|
+
let(:other) { described_class.new :baz, except: %i(foo), only: %i(bar) }
|
67
|
+
|
68
|
+
it "returns false" do
|
69
|
+
expect(subject == other).to eq false
|
70
|
+
expect(subject).not_to eq other
|
71
|
+
end
|
72
|
+
|
73
|
+
end # context
|
74
|
+
|
75
|
+
context "item with another blacklist" do
|
76
|
+
|
77
|
+
let(:other) { described_class.new :foo, except: %i(baz), only: %i(bar) }
|
78
|
+
|
79
|
+
it "returns false" do
|
80
|
+
expect(subject == other).to eq false
|
81
|
+
expect(subject).not_to eq other
|
82
|
+
end
|
83
|
+
|
84
|
+
end # context
|
85
|
+
|
86
|
+
context "item with another whitelist" do
|
87
|
+
|
88
|
+
let(:other) { described_class.new :foo, except: %i(foo), only: %i(baz) }
|
89
|
+
|
90
|
+
it "returns false" do
|
91
|
+
expect(subject == other).to eq false
|
92
|
+
expect(subject).not_to eq other
|
93
|
+
end
|
94
|
+
|
95
|
+
end # context
|
96
|
+
|
97
|
+
context "not an item" do
|
98
|
+
|
99
|
+
let(:other) { "baz" }
|
100
|
+
|
101
|
+
it "returns false" do
|
102
|
+
expect(subject == other).to eq false
|
103
|
+
expect(subject).not_to eq other
|
104
|
+
end
|
105
|
+
|
106
|
+
end # context
|
107
|
+
|
108
|
+
end # describe #==
|
109
|
+
|
110
|
+
describe "#used_in_context?" do
|
111
|
+
|
112
|
+
context "not restricted" do
|
113
|
+
|
114
|
+
it { is_expected.to be_used_in_context :bar }
|
115
|
+
it { is_expected.to be_used_in_context "baz" }
|
116
|
+
|
117
|
+
end # context
|
118
|
+
|
119
|
+
context "blacklisted" do
|
120
|
+
|
121
|
+
subject { described_class.new "foo", except: %w(foo bar) }
|
122
|
+
|
123
|
+
it { is_expected.not_to be_used_in_context "foo" }
|
124
|
+
it { is_expected.not_to be_used_in_context :bar }
|
125
|
+
it { is_expected.to be_used_in_context "baz" }
|
126
|
+
|
127
|
+
end # context
|
128
|
+
|
129
|
+
context "whitelisted" do
|
130
|
+
|
131
|
+
subject { described_class.new "foo", only: %w(foo bar) }
|
132
|
+
|
133
|
+
it { is_expected.to be_used_in_context "foo" }
|
134
|
+
it { is_expected.to be_used_in_context :bar }
|
135
|
+
it { is_expected.not_to be_used_in_context "baz" }
|
136
|
+
|
137
|
+
end # context
|
138
|
+
|
139
|
+
context "white- and blacklisted" do
|
140
|
+
|
141
|
+
subject do
|
142
|
+
described_class.new "foo", only: %w(foo bar), except: %w(bar baz)
|
143
|
+
end
|
144
|
+
|
145
|
+
it { is_expected.to be_used_in_context "foo" }
|
146
|
+
it { is_expected.not_to be_used_in_context :bar }
|
147
|
+
it { is_expected.not_to be_used_in_context "baz" }
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
end # describe #name
|
152
|
+
|
153
|
+
end # describe Attestor::Validation
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Attestor::Validations::Message do
|
4
|
+
|
5
|
+
let(:test_class) { Class.new }
|
6
|
+
before { TestModule = Module.new }
|
7
|
+
before { TestModule::TestObject = test_class }
|
8
|
+
after { Object.send :remove_const, :TestModule }
|
9
|
+
|
10
|
+
let(:scope) { test_class.new }
|
11
|
+
|
12
|
+
shared_examples "building frozen string" do
|
13
|
+
|
14
|
+
it { is_expected.to be_kind_of String }
|
15
|
+
it { is_expected.to be_frozen }
|
16
|
+
|
17
|
+
end # shared examples
|
18
|
+
|
19
|
+
describe ".new" do
|
20
|
+
|
21
|
+
context "with a symbol argument" do
|
22
|
+
|
23
|
+
subject { described_class.new :invalid, scope, foo: "bar" }
|
24
|
+
|
25
|
+
it_behaves_like "building frozen string"
|
26
|
+
|
27
|
+
it "translates the symbol in given scope" do
|
28
|
+
expect(I18n).to receive(:t) do |text, options|
|
29
|
+
expect(text).to eq :invalid
|
30
|
+
expect(options[:scope])
|
31
|
+
.to eq %w(attestor errors test_module/test_object)
|
32
|
+
expect(options[:default]).to eq "#{ scope } is invalid (invalid)"
|
33
|
+
expect(options[:foo]).to eq "bar"
|
34
|
+
""
|
35
|
+
end
|
36
|
+
subject
|
37
|
+
end
|
38
|
+
|
39
|
+
it "returns the translation" do
|
40
|
+
expect(subject).to eq "#{ scope } is invalid (invalid)"
|
41
|
+
end
|
42
|
+
|
43
|
+
end # context
|
44
|
+
|
45
|
+
context "with a non-symbolic argument" do
|
46
|
+
|
47
|
+
subject { described_class.new 1, scope }
|
48
|
+
|
49
|
+
it_behaves_like "building frozen string"
|
50
|
+
|
51
|
+
it "creates a stringified argument" do
|
52
|
+
expect(subject).to eq "1"
|
53
|
+
end
|
54
|
+
|
55
|
+
end # context
|
56
|
+
|
57
|
+
context "without options" do
|
58
|
+
|
59
|
+
subject { described_class.new :invalid, scope }
|
60
|
+
|
61
|
+
it_behaves_like "building frozen string"
|
62
|
+
|
63
|
+
it "returns the translation" do
|
64
|
+
expect(subject).to eq "#{ scope } is invalid (invalid)"
|
65
|
+
end
|
66
|
+
|
67
|
+
end # context
|
68
|
+
|
69
|
+
end # describe .new
|
70
|
+
|
71
|
+
end # Attestor::Validations::Invalid
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Attestor::Validations do
|
4
|
+
|
5
|
+
let(:collection_class) { Attestor::Validations::Collection }
|
6
|
+
let(:item_class) { Attestor::Validations::Item }
|
7
|
+
let(:message_class) { Attestor::Validations::Message }
|
8
|
+
let(:invalid_error) { Attestor::InvalidError }
|
9
|
+
let(:test_class) { Class.new.send(:include, described_class) }
|
10
|
+
|
11
|
+
before { Test = test_class }
|
12
|
+
after { Object.send :remove_const, :Test }
|
13
|
+
|
14
|
+
subject { test_class.new }
|
15
|
+
|
16
|
+
describe ".validations" do
|
17
|
+
|
18
|
+
it "returns a Collection" do
|
19
|
+
expect(test_class.validations).to be_kind_of collection_class
|
20
|
+
end
|
21
|
+
|
22
|
+
it "is empty by default" do
|
23
|
+
expect(test_class.validations.to_a).to be_empty
|
24
|
+
end
|
25
|
+
|
26
|
+
end # describe .validations
|
27
|
+
|
28
|
+
describe ".validate" do
|
29
|
+
|
30
|
+
context "without options" do
|
31
|
+
|
32
|
+
before { test_class.validate :foo }
|
33
|
+
|
34
|
+
it "adds the item to the collection" do
|
35
|
+
expect(test_class.validations.to_a).to eq [:foo]
|
36
|
+
end
|
37
|
+
|
38
|
+
end # context
|
39
|
+
|
40
|
+
context "with options" do
|
41
|
+
|
42
|
+
before { test_class.validate :foo, only: %w(bar baz), except: "bar" }
|
43
|
+
|
44
|
+
it "uses options" do
|
45
|
+
expect(test_class.validations.to_a).to eq [:foo]
|
46
|
+
expect(test_class.validations.set(:baz).to_a).to eq [:foo]
|
47
|
+
expect(test_class.validations.set(:bar).to_a).to eq []
|
48
|
+
end
|
49
|
+
|
50
|
+
end # context
|
51
|
+
|
52
|
+
end # describe .validate
|
53
|
+
|
54
|
+
describe "#validate" do
|
55
|
+
|
56
|
+
before do
|
57
|
+
test_class.validate :foo
|
58
|
+
test_class.validate :bar, only: :all
|
59
|
+
test_class.validate :baz, only: :foo
|
60
|
+
%i(foo bar baz).each { |method| allow(subject).to receive(method) }
|
61
|
+
end
|
62
|
+
|
63
|
+
context "without an argument" do
|
64
|
+
|
65
|
+
it "calls validations for :all context" do
|
66
|
+
expect(subject).to receive(:foo)
|
67
|
+
expect(subject).to receive(:bar)
|
68
|
+
expect(subject).not_to receive(:baz)
|
69
|
+
subject.validate
|
70
|
+
end
|
71
|
+
|
72
|
+
end # context
|
73
|
+
|
74
|
+
context ":foo" do
|
75
|
+
|
76
|
+
it "calls validations for :foo context" do
|
77
|
+
expect(subject).to receive(:foo)
|
78
|
+
expect(subject).to receive(:baz)
|
79
|
+
expect(subject).not_to receive(:bar)
|
80
|
+
subject.validate :foo
|
81
|
+
end
|
82
|
+
|
83
|
+
end # context
|
84
|
+
|
85
|
+
end # describe #validate
|
86
|
+
|
87
|
+
describe "#invalid" do
|
88
|
+
|
89
|
+
shared_examples "raising an error" do |name, options = {}|
|
90
|
+
|
91
|
+
let(:message) { message_class.new(name, subject, options) }
|
92
|
+
|
93
|
+
it "raises an InvalidError" do
|
94
|
+
expect { invalid }.to raise_error invalid_error
|
95
|
+
end
|
96
|
+
|
97
|
+
it "assings itself to the exception" do
|
98
|
+
begin
|
99
|
+
invalid
|
100
|
+
rescue => error
|
101
|
+
expect(error.object).to eq subject
|
102
|
+
expect(error.messages).to contain_exactly message
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end # shared examples
|
107
|
+
|
108
|
+
context "without options" do
|
109
|
+
|
110
|
+
let(:invalid) { subject.invalid :foo }
|
111
|
+
|
112
|
+
it_behaves_like "raising an error", :foo
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
context "with options" do
|
117
|
+
|
118
|
+
let(:invalid) { subject.invalid :foo, bar: :baz }
|
119
|
+
|
120
|
+
it_behaves_like "raising an error", :foo, bar: :baz
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end # invalid
|
125
|
+
|
126
|
+
end # describe Attestor::Validations
|