assertion 0.2.0 → 0.2.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 +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
|