mutations 0.5.0
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.
- data/.gitignore +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +16 -0
- data/README.md +271 -0
- data/Rakefile +8 -0
- data/lib/mutations.rb +24 -0
- data/lib/mutations/array_filter.rb +102 -0
- data/lib/mutations/boolean_filter.rb +33 -0
- data/lib/mutations/command.rb +149 -0
- data/lib/mutations/errors.rb +152 -0
- data/lib/mutations/exception.rb +13 -0
- data/lib/mutations/hash_filter.rb +131 -0
- data/lib/mutations/input_filter.rb +29 -0
- data/lib/mutations/integer_filter.rb +34 -0
- data/lib/mutations/model_filter.rb +52 -0
- data/lib/mutations/outcome.rb +19 -0
- data/lib/mutations/string_filter.rb +54 -0
- data/lib/mutations/version.rb +3 -0
- data/mutations.gemspec +19 -0
- data/spec/array_filter_spec.rb +150 -0
- data/spec/boolean_filter_spec.rb +55 -0
- data/spec/command_spec.rb +183 -0
- data/spec/default_spec.rb +0 -0
- data/spec/errors_spec.rb +93 -0
- data/spec/inheritance_spec.rb +39 -0
- data/spec/integer_filter_spec.rb +76 -0
- data/spec/model_filter_spec.rb +92 -0
- data/spec/mutations_spec.rb +9 -0
- data/spec/simple_command.rb +15 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/string_filter_spec.rb +138 -0
- metadata +108 -0
File without changes
|
data/spec/errors_spec.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe "Mutations - errors" do
|
4
|
+
|
5
|
+
class GivesErrors < Mutations::Command
|
6
|
+
required do
|
7
|
+
string :str1
|
8
|
+
string :str2, :in => %w(opt1 opt2 opt3)
|
9
|
+
end
|
10
|
+
|
11
|
+
optional do
|
12
|
+
integer :int1
|
13
|
+
hash :hash1 do
|
14
|
+
boolean :bool1
|
15
|
+
boolean :bool2
|
16
|
+
end
|
17
|
+
array :arr1 do integer end
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute
|
21
|
+
inputs
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns an ErrorHash as the top level error object, and ErrorAtom's inside" do
|
26
|
+
o = GivesErrors.run(hash1: 1, arr1: "bob")
|
27
|
+
|
28
|
+
assert !o.success?
|
29
|
+
assert o.errors.is_a?(Mutations::ErrorHash)
|
30
|
+
assert o.errors[:str1].is_a?(Mutations::ErrorAtom)
|
31
|
+
assert o.errors[:str2].is_a?(Mutations::ErrorAtom)
|
32
|
+
assert_nil o.errors[:int1]
|
33
|
+
assert o.errors[:hash1].is_a?(Mutations::ErrorAtom)
|
34
|
+
assert o.errors[:arr1].is_a?(Mutations::ErrorAtom)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "returns an ErrorHash for nested hashes" do
|
38
|
+
o = GivesErrors.run(hash1: {bool1: "poop"})
|
39
|
+
|
40
|
+
assert !o.success?
|
41
|
+
assert o.errors.is_a?(Mutations::ErrorHash)
|
42
|
+
assert o.errors[:hash1].is_a?(Mutations::ErrorHash)
|
43
|
+
assert o.errors[:hash1][:bool1].is_a?(Mutations::ErrorAtom)
|
44
|
+
assert o.errors[:hash1][:bool2].is_a?(Mutations::ErrorAtom)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "returns an ErrorArray for errors in arrays" do
|
48
|
+
o = GivesErrors.run(str1: "a", str2: "opt1", arr1: ["bob", 1, "sally"])
|
49
|
+
|
50
|
+
assert !o.success?
|
51
|
+
assert o.errors.is_a?(Mutations::ErrorHash)
|
52
|
+
assert o.errors[:arr1].is_a?(Mutations::ErrorArray)
|
53
|
+
assert o.errors[:arr1][0].is_a?(Mutations::ErrorAtom)
|
54
|
+
assert_nil o.errors[:arr1][1]
|
55
|
+
assert o.errors[:arr1][2].is_a?(Mutations::ErrorAtom)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "titleizes keys" do
|
59
|
+
atom = Mutations::ErrorAtom.new(:newsletter_subscription, :boolean)
|
60
|
+
assert_equal "Newsletter Subscription isn't a boolean", atom.message
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "Bunch o errors" do
|
64
|
+
before do
|
65
|
+
@outcome = GivesErrors.run(str1: "", str2: "opt9", int1: "zero", hash1: {bool1: "bob"}, arr1: ["bob", 1, "sally"])
|
66
|
+
end
|
67
|
+
|
68
|
+
it "gives symbolic errors" do
|
69
|
+
expected = {"str1"=>:empty,
|
70
|
+
"str2"=>:in,
|
71
|
+
"int1"=>:integer,
|
72
|
+
"hash1"=>{"bool1"=>:boolean, "bool2"=>:required},
|
73
|
+
"arr1"=>[:integer, nil, :integer]}
|
74
|
+
|
75
|
+
assert_equal expected, @outcome.errors.symbolic
|
76
|
+
end
|
77
|
+
|
78
|
+
it "gives messages" do
|
79
|
+
expected = {"str1"=>"Str1 can't be blank", "str2"=>"Str2 isn't an option", "int1"=>"Int1 isn't an integer", "hash1"=>{"bool1"=>"Bool1 isn't a boolean", "bool2"=>"Bool2 is required"}, "arr1"=>["Arr1[0] isn't an integer", nil, "Arr1[2] isn't an integer"]}
|
80
|
+
|
81
|
+
assert_equal expected, @outcome.errors.message
|
82
|
+
end
|
83
|
+
|
84
|
+
it "can flatten those messages" do
|
85
|
+
expected = ["Str1 can't be blank", "Str2 isn't an option", "Int1 isn't an integer", "Bool1 isn't a boolean", "Bool2 is required", "Arr1[0] isn't an integer", "Arr1[2] isn't an integer"]
|
86
|
+
|
87
|
+
assert_equal expected, @outcome.errors.message_list
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
require 'simple_command'
|
3
|
+
|
4
|
+
describe 'Mutations - inheritance' do
|
5
|
+
|
6
|
+
class SimpleInherited < SimpleCommand
|
7
|
+
|
8
|
+
required do
|
9
|
+
integer :age
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute
|
13
|
+
@filtered_input
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should filter with inherited command' do
|
18
|
+
mutation = SimpleInherited.run(name: "bob", email: "jon@jones.com", age: 10, amount: 22)
|
19
|
+
assert mutation.success?
|
20
|
+
assert_equal HashWithIndifferentAccess.new(name: "bob", email: "jon@jones.com", age: 10, amount: 22), mutation.result
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should filter with original command' do
|
24
|
+
mutation = SimpleCommand.run(name: "bob", email: "jon@jones.com", age: 10, amount: 22)
|
25
|
+
assert mutation.success?
|
26
|
+
assert_equal HashWithIndifferentAccess.new(name: "bob", email: "jon@jones.com", amount: 22), mutation.result
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'shouldnt collide' do
|
30
|
+
mutation = SimpleInherited.run(name: "bob", email: "jon@jones.com", age: 10, amount: 22)
|
31
|
+
assert mutation.success?
|
32
|
+
assert_equal HashWithIndifferentAccess.new(name: "bob", email: "jon@jones.com", age: 10, amount: 22), mutation.result
|
33
|
+
|
34
|
+
mutation = SimpleCommand.run(name: "bob", email: "jon@jones.com", age: 10, amount: 22)
|
35
|
+
assert mutation.success?
|
36
|
+
assert_equal HashWithIndifferentAccess.new(name: "bob", email: "jon@jones.com", amount: 22), mutation.result
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe "Mutations::IntegerFilter" do
|
4
|
+
|
5
|
+
it "allows integers" do
|
6
|
+
f = Mutations::IntegerFilter.new
|
7
|
+
filtered, errors = f.filter(3)
|
8
|
+
assert_equal 3, filtered
|
9
|
+
assert_equal nil, errors
|
10
|
+
end
|
11
|
+
|
12
|
+
it "allows strings that start with a digit" do
|
13
|
+
f = Mutations::IntegerFilter.new
|
14
|
+
filtered, errors = f.filter("3")
|
15
|
+
assert_equal 3, filtered
|
16
|
+
assert_equal nil, errors
|
17
|
+
end
|
18
|
+
|
19
|
+
it "allows negative strings" do
|
20
|
+
f = Mutations::IntegerFilter.new
|
21
|
+
filtered, errors = f.filter("-3")
|
22
|
+
assert_equal -3, filtered
|
23
|
+
assert_equal nil, errors
|
24
|
+
end
|
25
|
+
|
26
|
+
it "doesnt't allow other strings, nor does it allow random objects or symbols" do
|
27
|
+
f = Mutations::IntegerFilter.new
|
28
|
+
["zero","a1", {}, [], Object.new, :d].each do |thing|
|
29
|
+
filtered, errors = f.filter(thing)
|
30
|
+
assert_equal :integer, errors
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "considers nil to be invalid" do
|
35
|
+
f = Mutations::IntegerFilter.new(nils: false)
|
36
|
+
filtered, errors = f.filter(nil)
|
37
|
+
assert_equal nil, filtered
|
38
|
+
assert_equal :nils, errors
|
39
|
+
end
|
40
|
+
|
41
|
+
it "considers nil to be valid" do
|
42
|
+
f = Mutations::IntegerFilter.new(nils: true)
|
43
|
+
filtered, errors = f.filter(nil)
|
44
|
+
assert_equal nil, filtered
|
45
|
+
assert_equal nil, errors
|
46
|
+
end
|
47
|
+
|
48
|
+
it "considers low numbers invalid" do
|
49
|
+
f = Mutations::IntegerFilter.new(min: 10)
|
50
|
+
filtered, errors = f.filter(3)
|
51
|
+
assert_equal 3, filtered
|
52
|
+
assert_equal :min, errors
|
53
|
+
end
|
54
|
+
|
55
|
+
it "considers low numbers valid" do
|
56
|
+
f = Mutations::IntegerFilter.new(min: 10)
|
57
|
+
filtered, errors = f.filter(31)
|
58
|
+
assert_equal 31, filtered
|
59
|
+
assert_equal nil, errors
|
60
|
+
end
|
61
|
+
|
62
|
+
it "considers high numbers invalid" do
|
63
|
+
f = Mutations::IntegerFilter.new(max: 10)
|
64
|
+
filtered, errors = f.filter(31)
|
65
|
+
assert_equal 31, filtered
|
66
|
+
assert_equal :max, errors
|
67
|
+
end
|
68
|
+
|
69
|
+
it "considers high numbers vaild" do
|
70
|
+
f = Mutations::IntegerFilter.new(max: 10)
|
71
|
+
filtered, errors = f.filter(3)
|
72
|
+
assert_equal 3, filtered
|
73
|
+
assert_equal nil, errors
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe "Mutations::ModelFilter" do
|
4
|
+
|
5
|
+
class SimpleModel; end
|
6
|
+
class AlwaysNew
|
7
|
+
def new_record?
|
8
|
+
true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class AlwaysSaved
|
13
|
+
def new_record?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
it "allows models" do
|
20
|
+
f = Mutations::ModelFilter.new(:simple_model)
|
21
|
+
m = SimpleModel.new
|
22
|
+
filtered, errors = f.filter(m)
|
23
|
+
assert_equal m, filtered
|
24
|
+
assert_equal nil, errors
|
25
|
+
end
|
26
|
+
|
27
|
+
# it "disallows different types of models" do
|
28
|
+
# end
|
29
|
+
|
30
|
+
it "raises an exception during initialization if constantization fails" do
|
31
|
+
assert_raises NameError do
|
32
|
+
Mutations::ModelFilter.new(:complex_model)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "raises an exception during initialization if constantization of class fails" do
|
37
|
+
assert_raises NameError do
|
38
|
+
Mutations::ModelFilter.new(:simple_model, class: "ComplexModel")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it "raises an exception during initialization if constantization of builder fails" do
|
43
|
+
assert_raises NameError do
|
44
|
+
Mutations::ModelFilter.new(:simple_model, builder: "ComplexModel")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "considers nil to be invalid" do
|
49
|
+
f = Mutations::ModelFilter.new(:simple_model, nils: false)
|
50
|
+
filtered, errors = f.filter(nil)
|
51
|
+
assert_equal nil, filtered
|
52
|
+
assert_equal :nils, errors
|
53
|
+
end
|
54
|
+
|
55
|
+
it "considers nil to be valid" do
|
56
|
+
f = Mutations::ModelFilter.new(:simple_model, nils: true)
|
57
|
+
filtered, errors = f.filter(nil)
|
58
|
+
assert_equal nil, filtered
|
59
|
+
assert_equal nil, errors
|
60
|
+
end
|
61
|
+
|
62
|
+
# it "allows you to override class with a constant and succeed" do
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# it "allows you to override class with a string and succeed" do
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# it "allows you to override class and fail" do
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# it "allows anything if new_record is true" do
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# it "disallows new_records if new_record is false" do
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# it "allows saved records if new_record is false" do
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
# it "allows other records if new_record is false" do
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# it "allows you to build a record from a hash, and succeed" do
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# it "allows you to build a record from a hash, and fail" do
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# it "makes sure that if you build a record from a hash, it still has to be of the right class" do
|
90
|
+
# end
|
91
|
+
|
92
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe "Mutations::StringFilter" do
|
4
|
+
|
5
|
+
it "allows valid strings" do
|
6
|
+
sf = Mutations::StringFilter.new
|
7
|
+
filtered, errors = sf.filter("hello")
|
8
|
+
assert_equal "hello", filtered
|
9
|
+
assert_equal nil, errors
|
10
|
+
end
|
11
|
+
|
12
|
+
it "allows symbols" do
|
13
|
+
sf = Mutations::StringFilter.new
|
14
|
+
filtered, errors = sf.filter(:hello)
|
15
|
+
assert_equal "hello", filtered
|
16
|
+
assert_equal nil, errors
|
17
|
+
end
|
18
|
+
|
19
|
+
it "allows fixnums" do
|
20
|
+
sf = Mutations::StringFilter.new
|
21
|
+
filtered, errors = sf.filter(1)
|
22
|
+
assert_equal "1", filtered
|
23
|
+
assert_equal nil, errors
|
24
|
+
end
|
25
|
+
|
26
|
+
it "disallows non-string" do
|
27
|
+
sf = Mutations::StringFilter.new
|
28
|
+
[["foo"], {a: "1"}, Object.new].each do |thing|
|
29
|
+
filtered, errors = sf.filter(thing)
|
30
|
+
assert_equal :string, errors
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "strips" do
|
35
|
+
sf = Mutations::StringFilter.new(strip: true)
|
36
|
+
filtered, errors = sf.filter(" hello ")
|
37
|
+
assert_equal "hello", filtered
|
38
|
+
assert_equal nil, errors
|
39
|
+
end
|
40
|
+
|
41
|
+
it "doesn't strip" do
|
42
|
+
sf = Mutations::StringFilter.new(strip: false)
|
43
|
+
filtered, errors = sf.filter(" hello ")
|
44
|
+
assert_equal " hello ", filtered
|
45
|
+
assert_equal nil, errors
|
46
|
+
end
|
47
|
+
|
48
|
+
it "considers nil to be invalid" do
|
49
|
+
sf = Mutations::StringFilter.new(nils: false)
|
50
|
+
filtered, errors = sf.filter(nil)
|
51
|
+
assert_equal nil, filtered
|
52
|
+
assert_equal :nils, errors
|
53
|
+
end
|
54
|
+
|
55
|
+
it "considers nil to be valid" do
|
56
|
+
sf = Mutations::StringFilter.new(nils: true)
|
57
|
+
filtered, errors = sf.filter(nil)
|
58
|
+
assert_equal nil, filtered
|
59
|
+
assert_equal nil, errors
|
60
|
+
end
|
61
|
+
|
62
|
+
it "considers empty strings to be invalid" do
|
63
|
+
sf = Mutations::StringFilter.new(empty: false)
|
64
|
+
filtered, errors = sf.filter("")
|
65
|
+
assert_equal "", filtered
|
66
|
+
assert_equal :empty, errors
|
67
|
+
end
|
68
|
+
|
69
|
+
it "considers empty strings to be valid" do
|
70
|
+
sf = Mutations::StringFilter.new(empty: true)
|
71
|
+
filtered, errors = sf.filter("")
|
72
|
+
assert_equal "", filtered
|
73
|
+
assert_equal nil, errors
|
74
|
+
end
|
75
|
+
|
76
|
+
it "considers stripped strings that are empty to be invalid" do
|
77
|
+
sf = Mutations::StringFilter.new(empty: false)
|
78
|
+
filtered, errors = sf.filter(" ")
|
79
|
+
assert_equal "", filtered
|
80
|
+
assert_equal :empty, errors
|
81
|
+
end
|
82
|
+
|
83
|
+
it "considers long strings to be invalid" do
|
84
|
+
sf = Mutations::StringFilter.new(max_length: 5)
|
85
|
+
filtered, errors = sf.filter("123456")
|
86
|
+
assert_equal "123456", filtered
|
87
|
+
assert_equal :max_length, errors
|
88
|
+
end
|
89
|
+
|
90
|
+
it "considers long strings to be valid" do
|
91
|
+
sf = Mutations::StringFilter.new(max_length: 5)
|
92
|
+
filtered, errors = sf.filter("12345")
|
93
|
+
assert_equal "12345", filtered
|
94
|
+
assert_equal nil, errors
|
95
|
+
end
|
96
|
+
|
97
|
+
it "considers short strings to be invalid" do
|
98
|
+
sf = Mutations::StringFilter.new(min_length: 5)
|
99
|
+
filtered, errors = sf.filter("1234")
|
100
|
+
assert_equal "1234", filtered
|
101
|
+
assert_equal :min_length, errors
|
102
|
+
end
|
103
|
+
|
104
|
+
it "considers short strings to be valid" do
|
105
|
+
sf = Mutations::StringFilter.new(min_length: 5)
|
106
|
+
filtered, errors = sf.filter("12345")
|
107
|
+
assert_equal "12345", filtered
|
108
|
+
assert_equal nil, errors
|
109
|
+
end
|
110
|
+
|
111
|
+
it "considers bad matches to be invalid" do
|
112
|
+
sf = Mutations::StringFilter.new(matches: /aaa/)
|
113
|
+
filtered, errors = sf.filter("aab")
|
114
|
+
assert_equal "aab", filtered
|
115
|
+
assert_equal :matches, errors
|
116
|
+
end
|
117
|
+
|
118
|
+
it "considers good matches to be valid" do
|
119
|
+
sf = Mutations::StringFilter.new(matches: /aaa/)
|
120
|
+
filtered, errors = sf.filter("baaab")
|
121
|
+
assert_equal "baaab", filtered
|
122
|
+
assert_equal nil, errors
|
123
|
+
end
|
124
|
+
|
125
|
+
it "considers non-inclusion to be invalid" do
|
126
|
+
sf = Mutations::StringFilter.new(in: %w(red blue green))
|
127
|
+
filtered, errors = sf.filter("orange")
|
128
|
+
assert_equal "orange", filtered
|
129
|
+
assert_equal :in, errors
|
130
|
+
end
|
131
|
+
|
132
|
+
it "considers inclusion to be valid" do
|
133
|
+
sf = Mutations::StringFilter.new(in: %w(red blue green))
|
134
|
+
filtered, errors = sf.filter("red")
|
135
|
+
assert_equal "red", filtered
|
136
|
+
assert_equal nil, errors
|
137
|
+
end
|
138
|
+
end
|