knight 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/.travis.yml +9 -0
- data/Gemfile +7 -0
- data/Gemfile.dev +16 -0
- data/README.md +3 -1
- data/Rakefile +6 -1
- data/knight.gemspec +4 -1
- data/lib/knight.rb +18 -2
- data/lib/knight/error.rb +60 -0
- data/lib/knight/instance_methods.rb +69 -0
- data/lib/knight/result.rb +86 -0
- data/lib/knight/rule.rb +74 -0
- data/lib/knight/rule/exact_length.rb +63 -0
- data/lib/knight/rule/format.rb +62 -0
- data/lib/knight/rule/inclusion.rb +62 -0
- data/lib/knight/rule/maximum_length.rb +63 -0
- data/lib/knight/rule/minimum_length.rb +63 -0
- data/lib/knight/rule/presence.rb +37 -0
- data/lib/knight/rule/range_length.rb +64 -0
- data/lib/knight/validator.rb +91 -0
- data/lib/knight/version.rb +3 -1
- data/metrics/flog.yml +2 -0
- data/metrics/rubocop.yml +17 -0
- data/spec/integration/contextual_validator_spec.rb +41 -0
- data/spec/integration/knight_spec.rb +30 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/unit/knight/error/class_methods/new_spec.rb +15 -0
- data/spec/unit/knight/error/message_spec.rb +26 -0
- data/spec/unit/knight/instance_methods/class_methods/included_spec.rb +24 -0
- data/spec/unit/knight/instance_methods/class_methods/new_spec.rb +12 -0
- data/spec/unit/knight/instance_methods/class_methods/validator_spec.rb +13 -0
- data/spec/unit/knight/instance_methods/run_spec.rb +29 -0
- data/spec/unit/knight/result/class_methods/new_spec.rb +13 -0
- data/spec/unit/knight/result/errors_spec.rb +71 -0
- data/spec/unit/knight/result/valid_predicate_spec.rb +28 -0
- data/spec/unit/knight/rule/class_methods/new_spec.rb +38 -0
- data/spec/unit/knight/rule/error_spec.rb +29 -0
- data/spec/unit/knight/rule/exact_length/class_methods/new_spec.rb +27 -0
- data/spec/unit/knight/rule/exact_length/matches_predicate_spec.rb +19 -0
- data/spec/unit/knight/rule/exact_length/to_hash_spec.rb +12 -0
- data/spec/unit/knight/rule/format/class_methods/new_spec.rb +26 -0
- data/spec/unit/knight/rule/format/matches_predicate_spec.rb +31 -0
- data/spec/unit/knight/rule/format/to_hash_spec.rb +12 -0
- data/spec/unit/knight/rule/inclusion/class_methods/new_spec.rb +28 -0
- data/spec/unit/knight/rule/inclusion/matches_predicate_spec.rb +48 -0
- data/spec/unit/knight/rule/inclusion/to_hash_spec.rb +12 -0
- data/spec/unit/knight/rule/maximum_length/class_methods/new_spec.rb +27 -0
- data/spec/unit/knight/rule/maximum_length/matches_predicate_spec.rb +21 -0
- data/spec/unit/knight/rule/maximum_length/to_hash_spec.rb +12 -0
- data/spec/unit/knight/rule/minimum_length/class_methods/new_spec.rb +27 -0
- data/spec/unit/knight/rule/minimum_length/matches_predicate_spec.rb +21 -0
- data/spec/unit/knight/rule/minimum_length/to_hash_spec.rb +12 -0
- data/spec/unit/knight/rule/presence/matches_predicate_spec.rb +27 -0
- data/spec/unit/knight/rule/range_length/class_methods/new_spec.rb +27 -0
- data/spec/unit/knight/rule/range_length/matches_predicate_spec.rb +19 -0
- data/spec/unit/knight/rule/range_length/to_hash_spec.rb +12 -0
- data/spec/unit/knight/rule/to_hash_spec.rb +13 -0
- data/spec/unit/knight/validator/add_spec.rb +29 -0
- data/spec/unit/knight/validator/class_methods/new_spec.rb +18 -0
- data/spec/unit/knight/validator/context_spec.rb +13 -0
- data/spec/unit/knight/validator/rules_spec.rb +29 -0
- data/spec/unit/knight/validator/run_spec.rb +26 -0
- metadata +138 -6
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::ExactLength, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo, 3) }
|
9
|
+
let(:value) { 'abc' }
|
10
|
+
|
11
|
+
it { should be_true }
|
12
|
+
|
13
|
+
%w(ab abcdef).each do |value|
|
14
|
+
context "with value: #{value.inspect}" do
|
15
|
+
let(:value) { value }
|
16
|
+
it { should be_false }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::ExactLength, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:object) { described_class.new(:foo, 3) }
|
9
|
+
|
10
|
+
it { should be_frozen }
|
11
|
+
it { should eql({ attribute: :foo, length: 3 }) }
|
12
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Format, '.new' do
|
6
|
+
let(:attribute) { :foo }
|
7
|
+
let(:regexp) { /abc/ }
|
8
|
+
let(:options) { { message: 'message' } }
|
9
|
+
|
10
|
+
context 'with options' do
|
11
|
+
subject { described_class.new(attribute, regexp, options) }
|
12
|
+
|
13
|
+
it { should be_instance_of(described_class) }
|
14
|
+
its(:attribute_name) { should eql(attribute) }
|
15
|
+
its(:regexp) { should eql(regexp) }
|
16
|
+
its(:options) { should eql(options) }
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'with no options' do
|
20
|
+
subject { described_class.new(attribute, regexp) }
|
21
|
+
|
22
|
+
it { should be_instance_of(described_class) }
|
23
|
+
its(:options) { should be_empty }
|
24
|
+
its(:message) { should eql('%{attribute} has an invalid format') }
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Format, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo, /abc/) }
|
9
|
+
|
10
|
+
%w(
|
11
|
+
abcxxx
|
12
|
+
xxxabc
|
13
|
+
xxxabcxxx
|
14
|
+
).each do |value|
|
15
|
+
context "with value: #{value.inspect}" do
|
16
|
+
let(:value) { value }
|
17
|
+
it { should be_true }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
%w(
|
22
|
+
bcxxx
|
23
|
+
xxxac
|
24
|
+
xxxabxxx
|
25
|
+
).each do |value|
|
26
|
+
context "with value: #{value.inspect}" do
|
27
|
+
let(:value) { value }
|
28
|
+
it { should be_false }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Format, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:object) { described_class.new(:foo, /abc/) }
|
9
|
+
|
10
|
+
it { should be_frozen }
|
11
|
+
it { should eql({ attribute: :foo, format: /abc/ }) }
|
12
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Inclusion, '.new' do
|
6
|
+
subject { described_class.new(attribute, within) }
|
7
|
+
|
8
|
+
let(:attribute) { :foo }
|
9
|
+
let(:within) { 3..5 }
|
10
|
+
let(:options) { { message: 'message' } }
|
11
|
+
|
12
|
+
context 'with options' do
|
13
|
+
subject { described_class.new(attribute, within, options) }
|
14
|
+
|
15
|
+
it { should be_instance_of(described_class) }
|
16
|
+
its(:attribute_name) { should eql(attribute) }
|
17
|
+
its(:within) { should eql(within) }
|
18
|
+
its(:options) { should eql(options) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with no options' do
|
22
|
+
subject { described_class.new(attribute, within) }
|
23
|
+
|
24
|
+
it { should be_instance_of(described_class) }
|
25
|
+
its(:options) { should be_empty }
|
26
|
+
its(:message) { should eql('%{attribute} is not included in the list') }
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Inclusion, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo, within) }
|
9
|
+
|
10
|
+
context 'Array' do
|
11
|
+
let(:within) { [1, 2, 3] }
|
12
|
+
|
13
|
+
describe 'matched' do
|
14
|
+
let(:value) { 5 }
|
15
|
+
it { should be_false }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'not matched' do
|
19
|
+
let(:value) { 3 }
|
20
|
+
it { should be_true }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'Range' do
|
25
|
+
let(:within) { 1..3 }
|
26
|
+
|
27
|
+
describe 'matched' do
|
28
|
+
let(:value) { 5 }
|
29
|
+
it { should be_false }
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'not matched' do
|
33
|
+
let(:value) { 2 }
|
34
|
+
it { should be_true }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'cover? vs include?' do
|
39
|
+
let(:within) { double('within') }
|
40
|
+
let(:value) { 5 }
|
41
|
+
|
42
|
+
it 'send cover?' do
|
43
|
+
within.stub(:kind_of?).and_return(true)
|
44
|
+
within.should_receive(:cover?).with(value).and_return(false)
|
45
|
+
should be_false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Inclusion, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:object) { described_class.new(:foo, [2, 4]) }
|
9
|
+
|
10
|
+
it { should be_frozen }
|
11
|
+
it { should eql({ attribute: :foo, within: [2, 4] }) }
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::MaximumLength, '.new' do
|
6
|
+
|
7
|
+
let(:attribute) { :foo }
|
8
|
+
let(:maximum) { 3 }
|
9
|
+
let(:options) { { message: 'message' } }
|
10
|
+
|
11
|
+
context 'with options' do
|
12
|
+
subject { described_class.new(attribute, maximum, options) }
|
13
|
+
|
14
|
+
it { should be_instance_of(described_class) }
|
15
|
+
its(:attribute_name) { should eql(attribute) }
|
16
|
+
its(:maximum) { should eql(maximum) }
|
17
|
+
its(:options) { should eql(options) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with no options' do
|
21
|
+
subject { described_class.new(attribute, maximum) }
|
22
|
+
|
23
|
+
it { should be_instance_of(described_class) }
|
24
|
+
its(:options) { should be_empty }
|
25
|
+
its(:message) { should eql('%{attribute} is too long') }
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::MaximumLength, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo, 3) }
|
9
|
+
|
10
|
+
%w(ab abc).each do |value|
|
11
|
+
context "with value: #{value.inspect}" do
|
12
|
+
let(:value) { value }
|
13
|
+
it { should be_true }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'longer' do
|
18
|
+
let(:value) { 'abcd' }
|
19
|
+
it { should be_false }
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::MaximumLength, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:object) { described_class.new(:foo, 20) }
|
9
|
+
|
10
|
+
it { should be_frozen }
|
11
|
+
it { should eql({ attribute: :foo, maximum: 20 }) }
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::MinimumLength, '.new' do
|
6
|
+
|
7
|
+
let(:attribute) { :foo }
|
8
|
+
let(:minimum) { 3 }
|
9
|
+
let(:options) { { message: 'message' } }
|
10
|
+
|
11
|
+
context 'with options' do
|
12
|
+
subject { described_class.new(attribute, minimum, options) }
|
13
|
+
|
14
|
+
it { should be_instance_of(described_class) }
|
15
|
+
its(:attribute_name) { should eql(attribute) }
|
16
|
+
its(:minimum) { should eql(minimum) }
|
17
|
+
its(:options) { should eql(options) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with no options' do
|
21
|
+
subject { described_class.new(attribute, minimum) }
|
22
|
+
|
23
|
+
it { should be_instance_of(described_class) }
|
24
|
+
its(:options) { should be_empty }
|
25
|
+
its(:message) { should eql('%{attribute} is too short') }
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::MinimumLength, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo, 3) }
|
9
|
+
|
10
|
+
%w(abc abcd).each do |value|
|
11
|
+
context "with value: #{value.inspect}" do
|
12
|
+
let(:value) { value }
|
13
|
+
it { should be_true }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'shorter' do
|
18
|
+
let(:value) { 'ab' }
|
19
|
+
it { should be_false }
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::MinimumLength, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:object) { described_class.new(:foo, 4) }
|
9
|
+
|
10
|
+
it { should be_frozen }
|
11
|
+
it { should eql({ attribute: :foo, minimum: 4 }) }
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Presence, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo) }
|
9
|
+
|
10
|
+
[
|
11
|
+
nil,
|
12
|
+
'',
|
13
|
+
{},
|
14
|
+
[],
|
15
|
+
Set.new,
|
16
|
+
].each do |value|
|
17
|
+
context "with value: #{value.inspect}" do
|
18
|
+
let(:value) { value }
|
19
|
+
it { should be_false }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when the value is a string' do
|
24
|
+
let(:value) { 'bar' }
|
25
|
+
it { should be_true }
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::RangeLength, '.new' do
|
6
|
+
|
7
|
+
let(:attribute) { :foo }
|
8
|
+
let(:range) { 3..4 }
|
9
|
+
let(:options) { { message: 'message' } }
|
10
|
+
|
11
|
+
context 'with options' do
|
12
|
+
subject { described_class.new(attribute, range, options) }
|
13
|
+
|
14
|
+
it { should be_instance_of(described_class) }
|
15
|
+
its(:attribute_name) { should eql(attribute) }
|
16
|
+
its(:range) { should eql(range) }
|
17
|
+
its(:options) { should eql(options) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with no options' do
|
21
|
+
subject { described_class.new(attribute, range) }
|
22
|
+
|
23
|
+
it { should be_instance_of(described_class) }
|
24
|
+
its(:options) { should be_empty }
|
25
|
+
its(:message) { should eql('%{attribute} has an invalid length') }
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::RangeLength, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo, 3..5) }
|
9
|
+
let(:value) { 'abc' }
|
10
|
+
|
11
|
+
it { should be_true }
|
12
|
+
|
13
|
+
%w(ab abcdef).each do |value|
|
14
|
+
context "with value: #{value.inspect}" do
|
15
|
+
let(:value) { value }
|
16
|
+
it { should be_false }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::RangeLength, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:object) { described_class.new(:foo, (4...6)) }
|
9
|
+
|
10
|
+
it { should be_frozen }
|
11
|
+
it { should eql({ attribute: :foo, minimum: 4, maximum: 5 }) }
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:described_class) { Class.new(Rule) }
|
9
|
+
let(:object) { described_class.new(:foo) }
|
10
|
+
|
11
|
+
it { should be_frozen }
|
12
|
+
it { should eql({ attribute: :foo }) }
|
13
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Validator, '#add' do
|
6
|
+
subject { validator.rules(context) }
|
7
|
+
|
8
|
+
let(:validator) { described_class.new(rule1) }
|
9
|
+
let(:rule1) { Rule::ExactLength.new(:username, 10) }
|
10
|
+
let(:rule2) { Rule::Presence.new(:username) }
|
11
|
+
|
12
|
+
before do
|
13
|
+
validator.add(rule2, :register)
|
14
|
+
validator.add(rule2)
|
15
|
+
validator.add(nil)
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'default_context' do
|
19
|
+
let(:context) { :default }
|
20
|
+
specify { expect(subject.size).to eql(2) }
|
21
|
+
specify { expect(subject).to eql(Set.new([rule1, rule2])) }
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'register' do
|
25
|
+
let(:context) { :register }
|
26
|
+
specify { expect(subject.size).to eql(1) }
|
27
|
+
specify { expect(subject).to eql(Set.new([rule2])) }
|
28
|
+
end
|
29
|
+
end
|