assertion 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 +19 -0
- data/.yardopts +3 -0
- data/Gemfile +9 -0
- data/Guardfile +18 -0
- data/LICENSE +21 -0
- data/README.md +222 -0
- data/Rakefile +29 -0
- data/assertion.gemspec +27 -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 +72 -0
- data/config/metrics/saikuro.yml +3 -0
- data/config/metrics/simplecov.yml +6 -0
- data/config/metrics/yardstick.yml +37 -0
- data/lib/assertion.rb +79 -0
- data/lib/assertion/base.rb +186 -0
- data/lib/assertion/exceptions/invalid_error.rb +36 -0
- data/lib/assertion/exceptions/name_error.rb +29 -0
- data/lib/assertion/exceptions/not_implemented_error.rb +29 -0
- data/lib/assertion/inversion.rb +64 -0
- data/lib/assertion/inverter.rb +62 -0
- data/lib/assertion/state.rb +79 -0
- data/lib/assertion/transprocs/i18n.rb +55 -0
- data/lib/assertion/transprocs/inflector.rb +39 -0
- data/lib/assertion/transprocs/list.rb +30 -0
- data/lib/assertion/version.rb +9 -0
- data/spec/integration/assertion_spec.rb +50 -0
- data/spec/integration/en.yml +10 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/unit/assertion/base_spec.rb +221 -0
- data/spec/unit/assertion/exceptions/invalid_error_spec.rb +40 -0
- data/spec/unit/assertion/exceptions/name_error_spec.rb +26 -0
- data/spec/unit/assertion/exceptions/not_implemented_error_spec.rb +26 -0
- data/spec/unit/assertion/inversion_spec.rb +89 -0
- data/spec/unit/assertion/inverter_spec.rb +80 -0
- data/spec/unit/assertion/state_spec.rb +224 -0
- data/spec/unit/assertion/transprocs/i18n/to_scope_spec.rb +19 -0
- data/spec/unit/assertion/transprocs/i18n/translate_spec.rb +28 -0
- data/spec/unit/assertion/transprocs/inflector/to_path_spec.rb +19 -0
- data/spec/unit/assertion/transprocs/inflector/to_snake_path_spec.rb +19 -0
- data/spec/unit/assertion/transprocs/inflector/to_snake_spec.rb +19 -0
- data/spec/unit/assertion/transprocs/list/symbolize_spec.rb +19 -0
- data/spec/unit/assertion_spec.rb +65 -0
- metadata +171 -0
@@ -0,0 +1,10 @@
|
|
1
|
+
# Translations of messages for examples in the `./assertion_spec.rb`
|
2
|
+
---
|
3
|
+
en:
|
4
|
+
assertion:
|
5
|
+
is_adult:
|
6
|
+
right: "%{name} is an adult (age %{age})"
|
7
|
+
wrong: "%{name} is a child (age %{age})"
|
8
|
+
is_male:
|
9
|
+
right: "%{name} is a male"
|
10
|
+
wrong: "%{name} is a female"
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,221 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Assertion::Base do
|
4
|
+
|
5
|
+
let(:klass) { Class.new(described_class) }
|
6
|
+
before { allow(klass).to receive(:name) { "Test" } }
|
7
|
+
|
8
|
+
describe ".attributes" do
|
9
|
+
|
10
|
+
subject(:attributes) { klass.attributes }
|
11
|
+
|
12
|
+
it { is_expected.to eql [] }
|
13
|
+
|
14
|
+
end # describe .attributes
|
15
|
+
|
16
|
+
describe ".attribute" do
|
17
|
+
|
18
|
+
subject(:attribute) { klass.attribute names }
|
19
|
+
|
20
|
+
context "with valid name" do
|
21
|
+
|
22
|
+
let(:names) { :foo }
|
23
|
+
|
24
|
+
it "defines the attribute" do
|
25
|
+
expect { subject }
|
26
|
+
.to change { klass.attributes }
|
27
|
+
.to [:foo]
|
28
|
+
end
|
29
|
+
|
30
|
+
end # context
|
31
|
+
|
32
|
+
context "with array of names" do
|
33
|
+
|
34
|
+
let(:names) { [:foo, "bar", "foo"] }
|
35
|
+
|
36
|
+
it "defines the attribute" do
|
37
|
+
expect { subject }
|
38
|
+
.to change { klass.attributes }
|
39
|
+
.to [:foo, :bar]
|
40
|
+
end
|
41
|
+
|
42
|
+
end # context
|
43
|
+
|
44
|
+
context "with a :check name" do
|
45
|
+
|
46
|
+
let(:names) { [:check] }
|
47
|
+
|
48
|
+
it "fails" do
|
49
|
+
expect { subject }.to raise_error do |error|
|
50
|
+
expect(error).to be_kind_of Assertion::NameError
|
51
|
+
expect(error.message).to include "check"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end # context
|
56
|
+
|
57
|
+
context "with a :call name" do
|
58
|
+
|
59
|
+
let(:names) { [:call] }
|
60
|
+
|
61
|
+
it "fails" do
|
62
|
+
expect { subject }.to raise_error do |error|
|
63
|
+
expect(error).to be_kind_of Assertion::NameError
|
64
|
+
expect(error.message).to include "call"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end # context
|
69
|
+
|
70
|
+
end # describe .attribute
|
71
|
+
|
72
|
+
describe ".new" do
|
73
|
+
|
74
|
+
let(:klass) { Class.new(described_class) { attribute :foo, :bar } }
|
75
|
+
|
76
|
+
context "with attributes" do
|
77
|
+
|
78
|
+
subject { klass.new foo: :FOO, bar: :BAR, baz: :BAZ }
|
79
|
+
|
80
|
+
it "defines attributes" do
|
81
|
+
new_methods = subject.methods - described_class.instance_methods
|
82
|
+
expect(new_methods).to match_array [:foo, :bar]
|
83
|
+
end
|
84
|
+
|
85
|
+
it "initializes attributes" do
|
86
|
+
expect(subject.foo).to eql :FOO
|
87
|
+
expect(subject.bar).to eql :BAR
|
88
|
+
end
|
89
|
+
|
90
|
+
it { is_expected.to be_frozen }
|
91
|
+
|
92
|
+
end # context
|
93
|
+
|
94
|
+
context "without attributes" do
|
95
|
+
|
96
|
+
subject { klass.new }
|
97
|
+
|
98
|
+
it { is_expected.to be_frozen }
|
99
|
+
|
100
|
+
end # context
|
101
|
+
|
102
|
+
end # describe .new
|
103
|
+
|
104
|
+
describe ".not" do
|
105
|
+
|
106
|
+
subject { klass.not }
|
107
|
+
|
108
|
+
it "creates the iverter for the current class" do
|
109
|
+
expect(subject).to be_kind_of Assertion::Inverter
|
110
|
+
expect(subject.source).to eql klass
|
111
|
+
end
|
112
|
+
|
113
|
+
end # describe .not
|
114
|
+
|
115
|
+
describe ".[]" do
|
116
|
+
|
117
|
+
subject { klass[params] }
|
118
|
+
|
119
|
+
let(:params) { { foo: :FOO } }
|
120
|
+
let(:state) { double }
|
121
|
+
let(:assertion) { double call: state }
|
122
|
+
|
123
|
+
before { allow(klass).to receive(:new).with(params) { assertion } }
|
124
|
+
|
125
|
+
it "checks the assertion for given attributes" do
|
126
|
+
expect(subject).to eql state
|
127
|
+
end
|
128
|
+
|
129
|
+
end # describe .[]
|
130
|
+
|
131
|
+
describe "#attributes" do
|
132
|
+
|
133
|
+
let(:attrs) { { foo: :FOO, bar: :BAR } }
|
134
|
+
let(:klass) { Class.new(described_class) { attribute :foo, :bar } }
|
135
|
+
let(:assertion) { klass.new attrs }
|
136
|
+
|
137
|
+
subject { assertion.attributes }
|
138
|
+
it { is_expected.to eql attrs }
|
139
|
+
|
140
|
+
end # describe #attributes
|
141
|
+
|
142
|
+
describe "#message" do
|
143
|
+
|
144
|
+
let(:assertion) { klass.new }
|
145
|
+
|
146
|
+
context "for the truthy state" do
|
147
|
+
|
148
|
+
subject { assertion.message(true) }
|
149
|
+
it { is_expected.to eql "translation missing: en.assertion.test.right" }
|
150
|
+
|
151
|
+
end # context
|
152
|
+
|
153
|
+
context "for the falsey state" do
|
154
|
+
|
155
|
+
subject { assertion.message(false) }
|
156
|
+
it { is_expected.to eql "translation missing: en.assertion.test.wrong" }
|
157
|
+
|
158
|
+
end # context
|
159
|
+
|
160
|
+
context "by default" do
|
161
|
+
|
162
|
+
it "returns the message for the falsey state" do
|
163
|
+
expect(assertion.message).to eql assertion.message(false)
|
164
|
+
end
|
165
|
+
|
166
|
+
end # context
|
167
|
+
|
168
|
+
end # describe #message
|
169
|
+
|
170
|
+
describe "#check" do
|
171
|
+
|
172
|
+
subject { klass.new.check }
|
173
|
+
|
174
|
+
it "raises NotImplementedError" do
|
175
|
+
expect { subject }.to raise_error do |error|
|
176
|
+
expect(error).to be_kind_of Assertion::NotImplementedError
|
177
|
+
expect(error.message).to include("Test#check ")
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
end # describe #check
|
182
|
+
|
183
|
+
describe "#call" do
|
184
|
+
|
185
|
+
subject { assertion.call }
|
186
|
+
|
187
|
+
context "invalid assertion" do
|
188
|
+
|
189
|
+
let(:assertion) do
|
190
|
+
klass.__send__(:define_method, :check) { false }
|
191
|
+
klass.new
|
192
|
+
end
|
193
|
+
|
194
|
+
it "returns an invalid state" do
|
195
|
+
expect(subject).to be_kind_of Assertion::State
|
196
|
+
expect(subject).to be_invalid
|
197
|
+
end
|
198
|
+
|
199
|
+
it "adds a proper message to the state" do
|
200
|
+
expect(subject.messages).to contain_exactly assertion.message(false)
|
201
|
+
end
|
202
|
+
|
203
|
+
end # context
|
204
|
+
|
205
|
+
context "valid assertion" do
|
206
|
+
|
207
|
+
let(:assertion) do
|
208
|
+
klass.__send__(:define_method, :check) { true }
|
209
|
+
klass.new
|
210
|
+
end
|
211
|
+
|
212
|
+
it "returns a valid state" do
|
213
|
+
expect(subject).to be_kind_of Assertion::State
|
214
|
+
expect(subject).to be_valid
|
215
|
+
end
|
216
|
+
|
217
|
+
end # context
|
218
|
+
|
219
|
+
end # describe #call
|
220
|
+
|
221
|
+
end # describe Assertion
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Assertion::InvalidError do
|
4
|
+
|
5
|
+
subject(:error) { described_class.new messages }
|
6
|
+
let(:messages) { %w(foo bar) }
|
7
|
+
|
8
|
+
describe ".new" do
|
9
|
+
|
10
|
+
it { is_expected.to be_kind_of ::RuntimeError }
|
11
|
+
|
12
|
+
it { is_expected.to be_frozen }
|
13
|
+
|
14
|
+
end # describe .new
|
15
|
+
|
16
|
+
describe "#message" do
|
17
|
+
|
18
|
+
subject { error.message }
|
19
|
+
|
20
|
+
it "returns a proper message" do
|
21
|
+
expect(subject).to include "#{messages.inspect}"
|
22
|
+
end
|
23
|
+
|
24
|
+
end # describe #message
|
25
|
+
|
26
|
+
describe "#messages" do
|
27
|
+
|
28
|
+
subject { error.messages }
|
29
|
+
|
30
|
+
it { is_expected.to eql messages }
|
31
|
+
|
32
|
+
it { is_expected.to be_frozen }
|
33
|
+
|
34
|
+
it "doesn't freeze the source messages" do
|
35
|
+
expect(messages).not_to be_frozen
|
36
|
+
end
|
37
|
+
|
38
|
+
end # describe #message
|
39
|
+
|
40
|
+
end # describe Assertion::InvalidError
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Assertion::NameError do
|
4
|
+
|
5
|
+
subject(:error) { described_class.new :foo, :bar }
|
6
|
+
|
7
|
+
describe ".new" do
|
8
|
+
|
9
|
+
it { is_expected.to be_kind_of ::NameError }
|
10
|
+
|
11
|
+
it { is_expected.to be_frozen }
|
12
|
+
|
13
|
+
end # describe .new
|
14
|
+
|
15
|
+
describe "#message" do
|
16
|
+
|
17
|
+
subject(:message) { error.message }
|
18
|
+
|
19
|
+
it "returns a proper message" do
|
20
|
+
expect(subject)
|
21
|
+
.to include "Wrong name(s) for attribute(s): foo, bar"
|
22
|
+
end
|
23
|
+
|
24
|
+
end # describe #message
|
25
|
+
|
26
|
+
end # describe Assertion::NameError
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Assertion::NotImplementedError do
|
4
|
+
|
5
|
+
subject(:error) { described_class.new klass, :foo }
|
6
|
+
let(:klass) { double name: :Test }
|
7
|
+
|
8
|
+
describe ".new" do
|
9
|
+
|
10
|
+
it { is_expected.to be_kind_of ::NotImplementedError }
|
11
|
+
|
12
|
+
it { is_expected.to be_frozen }
|
13
|
+
|
14
|
+
end # describe .new
|
15
|
+
|
16
|
+
describe "#message" do
|
17
|
+
|
18
|
+
subject(:message) { error.message }
|
19
|
+
|
20
|
+
it "returns a proper message" do
|
21
|
+
expect(subject).to include "Test#foo method not implemented"
|
22
|
+
end
|
23
|
+
|
24
|
+
end # describe #message
|
25
|
+
|
26
|
+
end # describe Assertion::NotImplementedError
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Assertion::Inversion do
|
4
|
+
|
5
|
+
before { Adult = Assertion.about(:age) { age >= 18 } }
|
6
|
+
|
7
|
+
let(:assertion) { Adult.new age: 21 }
|
8
|
+
subject(:inversion) { described_class.new(assertion) }
|
9
|
+
subject(:double_inversion) { described_class.new(inversion) }
|
10
|
+
|
11
|
+
describe ".new" do
|
12
|
+
|
13
|
+
it { is_expected.to be_frozen }
|
14
|
+
|
15
|
+
end # describe .new
|
16
|
+
|
17
|
+
describe "#assertion" do
|
18
|
+
|
19
|
+
subject { inversion.assertion }
|
20
|
+
|
21
|
+
it { is_expected.to eql assertion }
|
22
|
+
|
23
|
+
end # describe #assertion
|
24
|
+
|
25
|
+
describe "#check" do
|
26
|
+
|
27
|
+
subject { instance.check }
|
28
|
+
|
29
|
+
it "is opposite to the assertion#check" do
|
30
|
+
expect(inversion.check).to eql !assertion.check
|
31
|
+
end
|
32
|
+
|
33
|
+
it "works for double inversion" do
|
34
|
+
expect(double_inversion.check).to eql assertion.check
|
35
|
+
end
|
36
|
+
|
37
|
+
end # describe #check
|
38
|
+
|
39
|
+
describe "#message" do
|
40
|
+
|
41
|
+
context "for the truthy state" do
|
42
|
+
|
43
|
+
it "is equal to wrong assertion" do
|
44
|
+
expect(inversion.message(true)).to eql assertion.message(false)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "works for double inversion" do
|
48
|
+
expect(double_inversion.message(true)).to eql assertion.message(true)
|
49
|
+
end
|
50
|
+
|
51
|
+
end # context
|
52
|
+
|
53
|
+
context "for the falsey state" do
|
54
|
+
|
55
|
+
it "is equal to right assertion" do
|
56
|
+
expect(inversion.message(false)).to eql assertion.message(true)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "works for double inversion" do
|
60
|
+
expect(double_inversion.message(false)).to eql assertion.message(false)
|
61
|
+
end
|
62
|
+
|
63
|
+
end # context
|
64
|
+
|
65
|
+
context "by default" do
|
66
|
+
|
67
|
+
it "returns the message for the falsey state" do
|
68
|
+
expect(inversion.message).to eql inversion.message(false)
|
69
|
+
end
|
70
|
+
|
71
|
+
end # context
|
72
|
+
|
73
|
+
end # describe #message
|
74
|
+
|
75
|
+
describe "#call" do
|
76
|
+
|
77
|
+
let(:state) { assertion.call }
|
78
|
+
subject { inversion.call }
|
79
|
+
|
80
|
+
it "creates the state opposite to the assertion's" do
|
81
|
+
expect(subject.valid?).to eql state.invalid?
|
82
|
+
expect(subject.messages).to contain_exactly assertion.message(true)
|
83
|
+
end
|
84
|
+
|
85
|
+
end # describe #call
|
86
|
+
|
87
|
+
after { Object.send :remove_const, :Adult }
|
88
|
+
|
89
|
+
end # describe Assertion::Inversion
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Assertion::Inverter do
|
4
|
+
|
5
|
+
let(:source) do
|
6
|
+
Man = Assertion.about(:age, :gender) { age.to_i >= 18 && gender == :male }
|
7
|
+
end
|
8
|
+
|
9
|
+
subject(:inverter) { described_class.new source }
|
10
|
+
|
11
|
+
describe ".new" do
|
12
|
+
|
13
|
+
it { is_expected.to be_frozen }
|
14
|
+
|
15
|
+
end # describe .new
|
16
|
+
|
17
|
+
describe ".source" do
|
18
|
+
|
19
|
+
subject { inverter.source }
|
20
|
+
it { is_expected.to eql source }
|
21
|
+
|
22
|
+
end # describe .source
|
23
|
+
|
24
|
+
describe "#new" do
|
25
|
+
|
26
|
+
let(:assertion) { inversion.assertion }
|
27
|
+
|
28
|
+
context "with attributes" do
|
29
|
+
|
30
|
+
subject(:inversion) { inverter.new age: 17, gender: :male }
|
31
|
+
|
32
|
+
it "returns an inversion" do
|
33
|
+
expect(inversion).to be_kind_of Assertion::Inversion
|
34
|
+
expect(assertion.attributes).to eql(age: 17, gender: :male)
|
35
|
+
end
|
36
|
+
|
37
|
+
end # context
|
38
|
+
|
39
|
+
context "without attributes" do
|
40
|
+
|
41
|
+
subject(:inversion) { inverter.new }
|
42
|
+
|
43
|
+
it "returns an inversion" do
|
44
|
+
expect(inversion).to be_kind_of Assertion::Inversion
|
45
|
+
expect(assertion.attributes).to eql(age: nil, gender: nil)
|
46
|
+
end
|
47
|
+
|
48
|
+
end # context
|
49
|
+
|
50
|
+
end # describe #new
|
51
|
+
|
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
|
+
after { Object.send :remove_const, :Man }
|
79
|
+
|
80
|
+
end # describe Assertion::Inverter
|