assertion 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +1 -1
- data/lib/assertion.rb +8 -4
- data/lib/assertion/base.rb +5 -3
- data/lib/assertion/dsl/attribute.rb +44 -0
- data/lib/assertion/dsl/attributes.rb +54 -0
- data/lib/assertion/dsl/builder.rb +81 -0
- data/lib/assertion/dsl/caller.rb +26 -0
- data/lib/assertion/dsl/inversion.rb +36 -0
- data/lib/assertion/guard.rb +2 -7
- data/lib/assertion/inverter.rb +2 -10
- data/lib/assertion/translator.rb +1 -1
- data/lib/assertion/version.rb +1 -1
- data/spec/unit/assertion/base_spec.rb +30 -137
- data/spec/unit/assertion/dsl/attribute_spec.rb +53 -0
- data/spec/unit/assertion/dsl/attributes_spec.rb +89 -0
- data/spec/unit/assertion/dsl/builder_spec.rb +123 -0
- data/spec/unit/assertion/dsl/caller_spec.rb +23 -0
- data/spec/unit/assertion/dsl/inversion_spec.rb +18 -0
- data/spec/unit/assertion/guard_spec.rb +10 -49
- data/spec/unit/assertion/inverter_spec.rb +4 -26
- data/spec/unit/assertion/translator_spec.rb +2 -0
- data/spec/unit/assertion_spec.rb +3 -116
- metadata +17 -5
- data/lib/assertion/base_dsl.rb +0 -75
- data/lib/assertion/dsl.rb +0 -77
- data/lib/assertion/guard_dsl.rb +0 -39
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Assertion::DSL::Attribute do
|
4
|
+
|
5
|
+
let(:klass) do
|
6
|
+
Class.new do
|
7
|
+
extend Assertion::DSL::Attribute
|
8
|
+
attr_reader :foo
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe ".extended" do
|
13
|
+
|
14
|
+
it "defines the #object" do
|
15
|
+
expect(klass.new).to respond_to :object
|
16
|
+
end
|
17
|
+
|
18
|
+
end # describe .extended
|
19
|
+
|
20
|
+
describe "#attribute" do
|
21
|
+
|
22
|
+
before { klass.send(:define_method, :object) { :object } }
|
23
|
+
|
24
|
+
shared_examples "aliasing #object" do |with: nil|
|
25
|
+
|
26
|
+
before { klass.attribute with }
|
27
|
+
let(:instance) { klass.new }
|
28
|
+
subject { instance.send with }
|
29
|
+
|
30
|
+
it { is_expected.to eql instance.object }
|
31
|
+
|
32
|
+
end # shared examples
|
33
|
+
|
34
|
+
shared_examples "complaining about wrong name" do |with: nil|
|
35
|
+
|
36
|
+
subject { klass.attribute with }
|
37
|
+
|
38
|
+
it "fails" do
|
39
|
+
expect { subject }.to raise_error do |error|
|
40
|
+
expect(error).to be_kind_of NameError
|
41
|
+
expect(error.message).to eql "#{klass}##{with} is already defined"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end # shared examples
|
46
|
+
|
47
|
+
it_behaves_like "aliasing #object", with: "bar"
|
48
|
+
it_behaves_like "complaining about wrong name", with: "foo"
|
49
|
+
it_behaves_like "complaining about wrong name", with: "state"
|
50
|
+
|
51
|
+
end # describe #attribute
|
52
|
+
|
53
|
+
end # describe Assertion::DSL::Attribute
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "ostruct"
|
4
|
+
|
5
|
+
describe Assertion::DSL::Attributes do
|
6
|
+
|
7
|
+
let(:klass) do
|
8
|
+
Class.new do
|
9
|
+
extend Assertion::DSL::Attributes
|
10
|
+
attr_reader :baz
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe ".extended" do
|
15
|
+
|
16
|
+
subject { klass.new.attributes }
|
17
|
+
|
18
|
+
it "defines hash of #attributes" do
|
19
|
+
expect(subject).to eql({})
|
20
|
+
end
|
21
|
+
|
22
|
+
end # describe .extended
|
23
|
+
|
24
|
+
describe "#attributes" do
|
25
|
+
|
26
|
+
subject { klass.attributes }
|
27
|
+
|
28
|
+
it { is_expected.to eql [] }
|
29
|
+
|
30
|
+
end # describe .attributes
|
31
|
+
|
32
|
+
describe "#attribute" do
|
33
|
+
|
34
|
+
before do
|
35
|
+
klass.send(:define_method, :attributes) { { foo: :FOO, bar: :BAR } }
|
36
|
+
end
|
37
|
+
|
38
|
+
shared_examples "defining attributes" do
|
39
|
+
|
40
|
+
let(:instance) { klass.new }
|
41
|
+
|
42
|
+
it "registers attributes" do
|
43
|
+
expect(klass.attributes).to eql [:foo, :bar]
|
44
|
+
end
|
45
|
+
|
46
|
+
it "declares attributes" do
|
47
|
+
expect(instance.foo).to eql :FOO
|
48
|
+
expect(instance.bar).to eql :BAR
|
49
|
+
end
|
50
|
+
|
51
|
+
end # shared examples
|
52
|
+
|
53
|
+
shared_examples "complaining about wrong name" do
|
54
|
+
|
55
|
+
subject { klass.attribute name }
|
56
|
+
|
57
|
+
it "fails" do
|
58
|
+
expect { subject }.to raise_error do |error|
|
59
|
+
expect(error).to be_kind_of NameError
|
60
|
+
expect(error.message).to eql "#{klass}##{name} is already defined"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end # shared examples
|
65
|
+
|
66
|
+
it_behaves_like "defining attributes" do
|
67
|
+
before { klass.attribute :foo }
|
68
|
+
before { klass.attribute :bar }
|
69
|
+
end
|
70
|
+
|
71
|
+
it_behaves_like "defining attributes" do
|
72
|
+
before { klass.attribute :foo, :bar }
|
73
|
+
end
|
74
|
+
|
75
|
+
it_behaves_like "defining attributes" do
|
76
|
+
before { klass.attribute %w(foo bar) }
|
77
|
+
end
|
78
|
+
|
79
|
+
it_behaves_like "complaining about wrong name" do
|
80
|
+
let(:name) { "baz" }
|
81
|
+
end
|
82
|
+
|
83
|
+
it_behaves_like "complaining about wrong name" do
|
84
|
+
let(:name) { "check" }
|
85
|
+
end
|
86
|
+
|
87
|
+
end # describe .attribute
|
88
|
+
|
89
|
+
end # describe Assertion::DSL::Attributes
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Assertion::DSL::Builder do
|
4
|
+
|
5
|
+
let(:klass) { Class.new { extend Assertion::DSL::Builder } }
|
6
|
+
let(:john) { { age: 17, gender: :male } }
|
7
|
+
let(:jack) { { age: 18, gender: :male } }
|
8
|
+
|
9
|
+
describe "#about" do
|
10
|
+
|
11
|
+
context "with attributes and a block" do
|
12
|
+
|
13
|
+
subject do
|
14
|
+
IsMan = klass.about(:age, :gender) { age >= 18 && gender == :male }
|
15
|
+
end
|
16
|
+
|
17
|
+
it "builds the assertion class" do
|
18
|
+
expect(subject.superclass).to eql Assertion::Base
|
19
|
+
end
|
20
|
+
|
21
|
+
it "implements the #check method" do
|
22
|
+
expect(subject[john]).to be_invalid
|
23
|
+
expect(subject[jack]).to be_valid
|
24
|
+
end
|
25
|
+
|
26
|
+
end # context
|
27
|
+
|
28
|
+
context "without attributes" do
|
29
|
+
|
30
|
+
subject do
|
31
|
+
IsMan = klass.about { true }
|
32
|
+
end
|
33
|
+
|
34
|
+
it "builds the assertion class" do
|
35
|
+
expect(subject.superclass).to eql Assertion::Base
|
36
|
+
end
|
37
|
+
|
38
|
+
it "implements the #check method" do
|
39
|
+
expect(subject[john]).to be_valid
|
40
|
+
expect(subject[jack]).to be_valid
|
41
|
+
end
|
42
|
+
|
43
|
+
end # context
|
44
|
+
|
45
|
+
context "without a block" do
|
46
|
+
|
47
|
+
subject do
|
48
|
+
IsMan = klass.about(:age, :gender)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "builds the assertion class" do
|
52
|
+
expect(subject.superclass).to eql Assertion::Base
|
53
|
+
end
|
54
|
+
|
55
|
+
it "doesn't implement the #check method" do
|
56
|
+
expect { subject.new(jack).check }.to raise_error NoMethodError
|
57
|
+
end
|
58
|
+
|
59
|
+
end # context
|
60
|
+
|
61
|
+
after { Object.send :remove_const, :IsMan }
|
62
|
+
|
63
|
+
end # describe .about
|
64
|
+
|
65
|
+
describe "#guards" do
|
66
|
+
|
67
|
+
before { IsAdult = klass.about(:age) { age.to_i >= 18 } }
|
68
|
+
|
69
|
+
context "with an attribute and a block" do
|
70
|
+
|
71
|
+
subject { klass.guards(:user) { IsAdult[user] } }
|
72
|
+
|
73
|
+
it "builds the guard class" do
|
74
|
+
expect(subject.superclass).to eql Assertion::Guard
|
75
|
+
end
|
76
|
+
|
77
|
+
it "defines an alias for the object" do
|
78
|
+
expect(subject.new(jack).user).to eql jack
|
79
|
+
end
|
80
|
+
|
81
|
+
it "implements the #state" do
|
82
|
+
expect { subject.new(jack).state }.not_to raise_error
|
83
|
+
end
|
84
|
+
|
85
|
+
end # context
|
86
|
+
|
87
|
+
context "without an attribute" do
|
88
|
+
|
89
|
+
subject { klass.guards { IsAdult[object] } }
|
90
|
+
|
91
|
+
it "builds the guard class" do
|
92
|
+
expect(subject.superclass).to eql Assertion::Guard
|
93
|
+
end
|
94
|
+
|
95
|
+
it "implements the #state of #object" do
|
96
|
+
expect { subject.new(jack).state }.not_to raise_error
|
97
|
+
end
|
98
|
+
|
99
|
+
end # context
|
100
|
+
|
101
|
+
context "without a block" do
|
102
|
+
|
103
|
+
subject { klass.guards(:user) }
|
104
|
+
|
105
|
+
it "builds the guard class" do
|
106
|
+
expect(subject.superclass).to eql Assertion::Guard
|
107
|
+
end
|
108
|
+
|
109
|
+
it "defines an alias for the object" do
|
110
|
+
expect(subject.new(jack).user).to eql jack
|
111
|
+
end
|
112
|
+
|
113
|
+
it "doesn't implement the #state" do
|
114
|
+
expect { subject.new(jack).state }.to raise_error NoMethodError
|
115
|
+
end
|
116
|
+
|
117
|
+
end # context
|
118
|
+
|
119
|
+
after { Object.send :remove_const, :IsAdult }
|
120
|
+
|
121
|
+
end # describe .guards
|
122
|
+
|
123
|
+
end # describe Assertion::DSL::Builder
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "ostruct"
|
4
|
+
|
5
|
+
describe Assertion::DSL::Caller do
|
6
|
+
|
7
|
+
let(:klass) do
|
8
|
+
Class.new(OpenStruct) do
|
9
|
+
extend Assertion::DSL::Caller
|
10
|
+
alias_method :call, :inspect
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#[]" do
|
15
|
+
|
16
|
+
it "works" do
|
17
|
+
args = { foo: :FOO, baz: :BAZ }
|
18
|
+
expect(klass[args]).to eql klass.new(args).call
|
19
|
+
end
|
20
|
+
|
21
|
+
end # describe #[]
|
22
|
+
|
23
|
+
end # describe Assertion::DSL::Caller
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Assertion::DSL::Inversion do
|
4
|
+
|
5
|
+
let(:klass) { Class.new { extend Assertion::DSL::Inversion } }
|
6
|
+
|
7
|
+
describe "#not" do
|
8
|
+
|
9
|
+
subject { klass.not }
|
10
|
+
|
11
|
+
it "creates the iverter for the current class" do
|
12
|
+
expect(subject).to be_kind_of Assertion::Inverter
|
13
|
+
expect(subject.source).to eql klass
|
14
|
+
end
|
15
|
+
|
16
|
+
end # describe .not
|
17
|
+
|
18
|
+
end # describe Assertion::DSL::Inversion
|
@@ -17,64 +17,25 @@ describe Assertion::Guard do
|
|
17
17
|
let(:invalid) { OpenStruct.new(name: "Ian", age: 10) }
|
18
18
|
let(:guard) { AdultOnly.new valid }
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
subject { AdultOnly.attribute name }
|
25
|
-
|
26
|
-
it "adds alias for the #object" do
|
27
|
-
subject
|
28
|
-
expect(guard.send name).to eql guard.object
|
29
|
-
end
|
30
|
-
|
31
|
-
end # shared examples
|
32
|
-
|
33
|
-
shared_examples "raising NameError" do |with: nil|
|
34
|
-
|
35
|
-
before { Test = Class.new(described_class) } # #state not implemented yet
|
36
|
-
after { Object.send :remove_const, :Test }
|
37
|
-
subject { Test.attribute with }
|
38
|
-
|
39
|
-
it "fails" do
|
40
|
-
expect { subject }.to raise_error do |error|
|
41
|
-
expect(error).to be_kind_of NameError
|
42
|
-
expect(error.message).to eql "Test##{with} is already defined"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
end # shared examples
|
47
|
-
|
48
|
-
it_behaves_like "adding #object alias", :foo
|
49
|
-
it_behaves_like "raising NameError", with: "state"
|
50
|
-
it_behaves_like "raising NameError", with: "call"
|
20
|
+
it "implements DSL::Caller" do
|
21
|
+
expect(AdultOnly).to be_kind_of Assertion::DSL::Caller
|
22
|
+
end
|
51
23
|
|
52
|
-
|
24
|
+
it "implements DSL::Attribute" do
|
25
|
+
expect(AdultOnly).to be_kind_of Assertion::DSL::Attribute
|
26
|
+
end
|
53
27
|
|
54
28
|
describe ".new" do
|
55
29
|
|
56
30
|
subject { guard }
|
57
31
|
|
58
|
-
it
|
59
|
-
|
60
|
-
end # describe .new
|
61
|
-
|
62
|
-
describe ".[]" do
|
63
|
-
|
64
|
-
it "returns the result of the call" do
|
65
|
-
expect(AdultOnly[valid]).to eql valid
|
66
|
-
expect { AdultOnly[invalid] }.to raise_error Assertion::InvalidError
|
32
|
+
it "initializes the object" do
|
33
|
+
expect(guard.object).to eql valid
|
67
34
|
end
|
68
35
|
|
69
|
-
|
70
|
-
|
71
|
-
describe "#object" do
|
72
|
-
|
73
|
-
subject { guard.object }
|
74
|
-
|
75
|
-
it { is_expected.to eql valid }
|
36
|
+
it { is_expected.to be_frozen }
|
76
37
|
|
77
|
-
end # describe
|
38
|
+
end # describe .new
|
78
39
|
|
79
40
|
describe "#call" do
|
80
41
|
|
@@ -8,6 +8,10 @@ describe Assertion::Inverter do
|
|
8
8
|
|
9
9
|
subject(:inverter) { described_class.new source }
|
10
10
|
|
11
|
+
it "implements DSL::Caller" do
|
12
|
+
expect(inverter).to be_kind_of Assertion::DSL::Caller
|
13
|
+
end
|
14
|
+
|
11
15
|
describe ".new" do
|
12
16
|
|
13
17
|
it { is_expected.to be_frozen }
|
@@ -49,32 +53,6 @@ describe Assertion::Inverter do
|
|
49
53
|
|
50
54
|
end # describe #new
|
51
55
|
|
52
|
-
describe "#[]" do
|
53
|
-
|
54
|
-
context "with attributes" do
|
55
|
-
|
56
|
-
subject(:state) { inverter[age: 18, gender: :male] }
|
57
|
-
|
58
|
-
it "provides the state for inversion" do
|
59
|
-
expect(state).to be_kind_of Assertion::State
|
60
|
-
expect(state).to be_invalid
|
61
|
-
end
|
62
|
-
|
63
|
-
end # context
|
64
|
-
|
65
|
-
context "without attributes" do
|
66
|
-
|
67
|
-
subject(:state) { inverter[] }
|
68
|
-
|
69
|
-
it "provides the state for inversion" do
|
70
|
-
expect(state).to be_kind_of Assertion::State
|
71
|
-
expect(state).to be_valid
|
72
|
-
end
|
73
|
-
|
74
|
-
end # context
|
75
|
-
|
76
|
-
end # describe #[]
|
77
|
-
|
78
56
|
after { Object.send :remove_const, :IsMan }
|
79
57
|
|
80
58
|
end # describe Assertion::Inverter
|
@@ -50,7 +50,9 @@ describe Assertion::Translator do
|
|
50
50
|
end # shared examples
|
51
51
|
|
52
52
|
it_behaves_like "translating", true, to: "truthy"
|
53
|
+
it_behaves_like "translating", "ok", to: "truthy"
|
53
54
|
it_behaves_like "translating", false, to: "falsey"
|
55
|
+
it_behaves_like "translating", nil, to: "falsey"
|
54
56
|
|
55
57
|
end # describe #call
|
56
58
|
|
data/spec/unit/assertion_spec.rb
CHANGED
@@ -2,121 +2,8 @@
|
|
2
2
|
|
3
3
|
describe Assertion do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
describe ".about" do
|
9
|
-
|
10
|
-
context "with attributes and a block" do
|
11
|
-
|
12
|
-
subject do
|
13
|
-
IsMan = Assertion.about(:age, :gender) { age >= 18 && gender == :male }
|
14
|
-
end
|
15
|
-
|
16
|
-
it "builds the assertion class" do
|
17
|
-
expect(subject.superclass).to eql Assertion::Base
|
18
|
-
end
|
19
|
-
|
20
|
-
it "implements the #check method" do
|
21
|
-
expect(subject[john]).to be_invalid
|
22
|
-
expect(subject[jack]).to be_valid
|
23
|
-
end
|
24
|
-
|
25
|
-
end # context
|
26
|
-
|
27
|
-
context "without attributes" do
|
28
|
-
|
29
|
-
subject do
|
30
|
-
IsMan = Assertion.about { true }
|
31
|
-
end
|
32
|
-
|
33
|
-
it "builds the assertion class" do
|
34
|
-
expect(subject.superclass).to eql Assertion::Base
|
35
|
-
end
|
36
|
-
|
37
|
-
it "implements the #check method" do
|
38
|
-
expect(subject[john]).to be_valid
|
39
|
-
expect(subject[jack]).to be_valid
|
40
|
-
end
|
41
|
-
|
42
|
-
end # context
|
43
|
-
|
44
|
-
context "without a block" do
|
45
|
-
|
46
|
-
subject do
|
47
|
-
IsMan = Assertion.about(:age, :gender)
|
48
|
-
end
|
49
|
-
|
50
|
-
it "builds the assertion class" do
|
51
|
-
expect(subject.superclass).to eql Assertion::Base
|
52
|
-
end
|
53
|
-
|
54
|
-
it "doesn't implement the #check method" do
|
55
|
-
expect { subject.new(jack).check }.to raise_error NoMethodError
|
56
|
-
end
|
57
|
-
|
58
|
-
end # context
|
59
|
-
|
60
|
-
after { Object.send :remove_const, :IsMan }
|
61
|
-
|
62
|
-
end # describe .about
|
63
|
-
|
64
|
-
describe ".guards" do
|
65
|
-
|
66
|
-
before { IsAdult = Assertion.about(:age) { age.to_i >= 18 } }
|
67
|
-
|
68
|
-
context "with an attribute and a block" do
|
69
|
-
|
70
|
-
subject { Assertion.guards(:user) { IsAdult[user] } }
|
71
|
-
|
72
|
-
it "builds the guard class" do
|
73
|
-
expect(subject.superclass).to eql Assertion::Guard
|
74
|
-
end
|
75
|
-
|
76
|
-
it "defines an alias for the object" do
|
77
|
-
expect(subject.new(jack).user).to eql jack
|
78
|
-
end
|
79
|
-
|
80
|
-
it "implements the #state" do
|
81
|
-
expect { subject.new(jack).state }.not_to raise_error
|
82
|
-
end
|
83
|
-
|
84
|
-
end # context
|
85
|
-
|
86
|
-
context "without an attribute" do
|
87
|
-
|
88
|
-
subject { Assertion.guards { IsAdult[object] } }
|
89
|
-
|
90
|
-
it "builds the guard class" do
|
91
|
-
expect(subject.superclass).to eql Assertion::Guard
|
92
|
-
end
|
93
|
-
|
94
|
-
it "implements the #state of #object" do
|
95
|
-
expect { subject.new(jack).state }.not_to raise_error
|
96
|
-
end
|
97
|
-
|
98
|
-
end # context
|
99
|
-
|
100
|
-
context "without a block" do
|
101
|
-
|
102
|
-
subject { Assertion.guards(:user) }
|
103
|
-
|
104
|
-
it "builds the guard class" do
|
105
|
-
expect(subject.superclass).to eql Assertion::Guard
|
106
|
-
end
|
107
|
-
|
108
|
-
it "defines an alias for the object" do
|
109
|
-
expect(subject.new(jack).user).to eql jack
|
110
|
-
end
|
111
|
-
|
112
|
-
it "doesn't implement the #state" do
|
113
|
-
expect { subject.new(jack).state }.to raise_error NoMethodError
|
114
|
-
end
|
115
|
-
|
116
|
-
end # context
|
117
|
-
|
118
|
-
after { Object.send :remove_const, :IsAdult }
|
119
|
-
|
120
|
-
end # describe .guards
|
5
|
+
it "extends DSL::Builder" do
|
6
|
+
expect(described_class).to be_kind_of Assertion::DSL::Builder
|
7
|
+
end
|
121
8
|
|
122
9
|
end # describe Assertion
|