membrane 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.
- data/.gitignore +2 -0
- data/Gemfile +4 -0
- data/LICENSE +7136 -0
- data/README.md +90 -0
- data/Rakefile +14 -0
- data/lib/membrane/errors.rb +3 -0
- data/lib/membrane/schema/any.rb +13 -0
- data/lib/membrane/schema/base.rb +17 -0
- data/lib/membrane/schema/bool.rb +20 -0
- data/lib/membrane/schema/class.rb +24 -0
- data/lib/membrane/schema/dictionary.rb +40 -0
- data/lib/membrane/schema/enum.rb +30 -0
- data/lib/membrane/schema/list.rb +37 -0
- data/lib/membrane/schema/record.rb +45 -0
- data/lib/membrane/schema/regexp.rb +29 -0
- data/lib/membrane/schema/tuple.rb +48 -0
- data/lib/membrane/schema/value.rb +22 -0
- data/lib/membrane/schema.rb +17 -0
- data/lib/membrane/schema_parser.rb +186 -0
- data/lib/membrane/version.rb +3 -0
- data/lib/membrane.rb +4 -0
- data/membrane.gemspec +25 -0
- data/spec/any_schema_spec.rb +14 -0
- data/spec/bool_schema_spec.rb +18 -0
- data/spec/class_schema_spec.rb +22 -0
- data/spec/complex_schema_spec.rb +50 -0
- data/spec/dictionary_schema_spec.rb +57 -0
- data/spec/enum_schema_spec.rb +17 -0
- data/spec/list_schema_spec.rb +46 -0
- data/spec/record_schema_spec.rb +56 -0
- data/spec/regexp_schema_spec.rb +19 -0
- data/spec/schema_parser_spec.rb +249 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/tuple_schema_spec.rb +29 -0
- data/spec/value_schema_spec.rb +16 -0
- metadata +142 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Membrane::Schema::Any do
|
4
|
+
describe "#validate" do
|
5
|
+
it "should always return nil" do
|
6
|
+
schema = Membrane::Schema::Any.new
|
7
|
+
# Smoke test more than anything. Cannot validate this with 100%
|
8
|
+
# certainty.
|
9
|
+
[1, "hi", :test, {}, []].each do |o|
|
10
|
+
schema.validate(o).should be_nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
|
4
|
+
describe Membrane::Schema::Bool do
|
5
|
+
describe "#validate" do
|
6
|
+
let(:schema) { Membrane::Schema::Bool.new }
|
7
|
+
|
8
|
+
it "should return nil for {true, false}" do
|
9
|
+
[true, false].each { |v| schema.validate(v).should be_nil }
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should return an error for values not in {true, false}" do
|
13
|
+
["a", 1].each do |v|
|
14
|
+
expect_validation_failure(schema, v, /true or false/)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
|
4
|
+
describe Membrane::Schema::Class do
|
5
|
+
describe "#validate" do
|
6
|
+
let(:schema) { Membrane::Schema::Class.new(String) }
|
7
|
+
|
8
|
+
it "should return nil for instances of the supplied class" do
|
9
|
+
schema.validate("test").should be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should return nil for subclasses of the supplied class" do
|
13
|
+
class StrTest < String; end
|
14
|
+
|
15
|
+
schema.validate(StrTest.new("hi")).should be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should return an error for non class instances" do
|
19
|
+
expect_validation_failure(schema, 10, /instance of String/)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Membrane do
|
4
|
+
let(:schema) do
|
5
|
+
Membrane::SchemaParser.parse do
|
6
|
+
{ "ints" => [Integer],
|
7
|
+
"tf" => bool,
|
8
|
+
"any" => any,
|
9
|
+
"1_or_2" => enum(1, 2),
|
10
|
+
"str_to_str_to_int" => dict(String, dict(String, Integer)),
|
11
|
+
optional("optional") => bool,
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:valid) do
|
17
|
+
{ "ints" => [1, 2],
|
18
|
+
"tf" => false,
|
19
|
+
"any" => nil,
|
20
|
+
"1_or_2" => 2,
|
21
|
+
"optional" => true,
|
22
|
+
"str_to_str_to_int" => { "ten" => { "twenty" => 20 } },
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should work with complex nested schemas" do
|
27
|
+
schema.validate(valid).should be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should complain about missing keys" do
|
31
|
+
required_keys = schema.schemas.keys.dup
|
32
|
+
required_keys.delete("optional")
|
33
|
+
|
34
|
+
required_keys.each do |k|
|
35
|
+
invalid = valid.dup
|
36
|
+
|
37
|
+
invalid.delete(k)
|
38
|
+
|
39
|
+
expect_validation_failure(schema, invalid, /#{k} => Missing key/)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should validate nested maps" do
|
44
|
+
invalid = valid.dup
|
45
|
+
|
46
|
+
invalid["str_to_str_to_int"]["ten"]["twenty"] = "invalid"
|
47
|
+
|
48
|
+
expect_validation_failure(schema, invalid, /twenty => Expected/)
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Membrane::Schema::Dictionary do
|
4
|
+
describe "#validate" do
|
5
|
+
let (:data) { { "foo" => 1, "bar" => 2 } }
|
6
|
+
|
7
|
+
it "should return an error if supplied with a non-hash" do
|
8
|
+
schema = Membrane::Schema::Dictionary.new(nil, nil)
|
9
|
+
|
10
|
+
expect_validation_failure(schema, "test", /instance of Hash/)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should validate each key against the supplied key schema" do
|
14
|
+
key_schema = mock("key_schema")
|
15
|
+
|
16
|
+
data.keys.each { |k| key_schema.should_receive(:validate).with(k) }
|
17
|
+
|
18
|
+
dict_schema = Membrane::Schema::Dictionary.new(key_schema,
|
19
|
+
Membrane::Schema::Any.new)
|
20
|
+
|
21
|
+
dict_schema.validate(data)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should validate the value for each valid key" do
|
25
|
+
key_schema = Membrane::Schema::Class.new(String)
|
26
|
+
val_schema = mock("val_schema")
|
27
|
+
|
28
|
+
data.values.each { |v| val_schema.should_receive(:validate).with(v) }
|
29
|
+
|
30
|
+
dict_schema = Membrane::Schema::Dictionary.new(key_schema, val_schema)
|
31
|
+
|
32
|
+
dict_schema.validate(data)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return any errors for keys or values that didn't validate" do
|
36
|
+
bad_data = {
|
37
|
+
"foo" => "bar",
|
38
|
+
:bar => 2,
|
39
|
+
}
|
40
|
+
|
41
|
+
key_schema = Membrane::Schema::Class.new(String)
|
42
|
+
val_schema = Membrane::Schema::Class.new(Integer)
|
43
|
+
dict_schema = Membrane::Schema::Dictionary.new(key_schema, val_schema)
|
44
|
+
|
45
|
+
errors = nil
|
46
|
+
|
47
|
+
begin
|
48
|
+
dict_schema.validate(bad_data)
|
49
|
+
rescue Membrane::SchemaValidationError => e
|
50
|
+
errors = e.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
errors.should match(/foo/)
|
54
|
+
errors.should match(/bar/)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Membrane::Schema::Enum do
|
4
|
+
describe "#validate" do
|
5
|
+
let (:int_schema) { Membrane::Schema::Class.new(Integer) }
|
6
|
+
let (:str_schema) { Membrane::Schema::Class.new(String) }
|
7
|
+
let (:enum_schema) { Membrane::Schema::Enum.new(int_schema, str_schema) }
|
8
|
+
|
9
|
+
it "should return an error if none of the schemas validate" do
|
10
|
+
expect_validation_failure(enum_schema, :sym, /doesn't validate/)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return nil if any of the schemas validate" do
|
14
|
+
enum_schema.validate("foo").should be_nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Membrane::Schema::List do
|
4
|
+
describe "#validate" do
|
5
|
+
it "should return an error if the validated object isn't an array" do
|
6
|
+
schema = Membrane::Schema::List.new(nil)
|
7
|
+
|
8
|
+
expect_validation_failure(schema, "hi", /instance of Array/)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should invoke validate each list item against the supplied schema" do
|
12
|
+
item_schema = mock("item_schema")
|
13
|
+
|
14
|
+
data = [0, 1, 2]
|
15
|
+
|
16
|
+
data.each { |x| item_schema.should_receive(:validate).with(x) }
|
17
|
+
|
18
|
+
list_schema = Membrane::Schema::List.new(item_schema)
|
19
|
+
|
20
|
+
list_schema.validate(data)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return an error if any items fail to validate" do
|
25
|
+
item_schema = Membrane::Schema::Class.new(Integer)
|
26
|
+
list_schema = Membrane::Schema::List.new(item_schema)
|
27
|
+
|
28
|
+
errors = nil
|
29
|
+
|
30
|
+
begin
|
31
|
+
list_schema.validate([1, 2, "hi", 3, :there])
|
32
|
+
rescue Membrane::SchemaValidationError => e
|
33
|
+
errors = e.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
errors.should match(/index 2/)
|
37
|
+
errors.should match(/index 4/)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should return nil if all items validate" do
|
41
|
+
item_schema = Membrane::Schema::Class.new(Integer)
|
42
|
+
list_schema = Membrane::Schema::List.new(item_schema)
|
43
|
+
|
44
|
+
list_schema.validate([1, 2, 3]).should be_nil
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Membrane::Schema::Record do
|
4
|
+
describe "#validate" do
|
5
|
+
it "should return an error if the validated object isn't a hash" do
|
6
|
+
schema = Membrane::Schema::Record.new(nil)
|
7
|
+
|
8
|
+
expect_validation_failure(schema, "test", /instance of Hash/)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should return an error for missing keys" do
|
12
|
+
key_schemas = { "foo" => Membrane::Schema::ANY }
|
13
|
+
rec_schema = Membrane::Schema::Record.new(key_schemas)
|
14
|
+
|
15
|
+
expect_validation_failure(rec_schema, {}, /foo => Missing/)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should validate the value for each key" do
|
19
|
+
data = {
|
20
|
+
"foo" => 1,
|
21
|
+
"bar" => 2,
|
22
|
+
}
|
23
|
+
|
24
|
+
key_schemas = {
|
25
|
+
"foo" => mock("foo"),
|
26
|
+
"bar" => mock("bar"),
|
27
|
+
}
|
28
|
+
|
29
|
+
key_schemas.each { |k, m| m.should_receive(:validate).with(data[k]) }
|
30
|
+
|
31
|
+
rec_schema = Membrane::Schema::Record.new(key_schemas)
|
32
|
+
|
33
|
+
rec_schema.validate(data)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return all errors for keys or values that didn't validate" do
|
37
|
+
key_schemas = {
|
38
|
+
"foo" => Membrane::Schema::ANY,
|
39
|
+
"bar" => Membrane::Schema::Class.new(String),
|
40
|
+
}
|
41
|
+
|
42
|
+
rec_schema = Membrane::Schema::Record.new(key_schemas)
|
43
|
+
|
44
|
+
errors = nil
|
45
|
+
|
46
|
+
begin
|
47
|
+
rec_schema.validate({ "bar" => 2 })
|
48
|
+
rescue Membrane::SchemaValidationError => e
|
49
|
+
errors = e.to_s
|
50
|
+
end
|
51
|
+
|
52
|
+
errors.should match(/foo => Missing key/)
|
53
|
+
errors.should match(/bar/)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Membrane::Schema::Regexp do
|
4
|
+
let(:schema) { Membrane::Schema::Regexp.new(/bar/) }
|
5
|
+
|
6
|
+
describe "#validate" do
|
7
|
+
it "should raise an error if the validated object isn't a string" do
|
8
|
+
expect_validation_failure(schema, 5, /instance of String/)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should raise an error if the validated object doesn't match" do
|
12
|
+
expect_validation_failure(schema, "invalid", /match regex/)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return nil if the validated object matches" do
|
16
|
+
schema.validate("barbar").should be_nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Membrane::SchemaParser do
|
4
|
+
let(:parser) { Membrane::SchemaParser.new }
|
5
|
+
|
6
|
+
describe "#deparse" do
|
7
|
+
it "should call inspect on the value of a Value schema" do
|
8
|
+
val = "test"
|
9
|
+
val.should_receive(:inspect).twice
|
10
|
+
schema = Membrane::Schema::Value.new(val)
|
11
|
+
|
12
|
+
parser.deparse(schema).should == val.inspect
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return 'any' for instance of Membrane::Schema::Any" do
|
16
|
+
schema = Membrane::Schema::Any.new
|
17
|
+
|
18
|
+
parser.deparse(schema).should == "any"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return 'bool' for instances of Membrane::Schema::Bool" do
|
22
|
+
schema = Membrane::Schema::Bool.new
|
23
|
+
|
24
|
+
parser.deparse(schema).should == "bool"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should call inspect on the class of a Membrane::Schema::Class schema" do
|
28
|
+
klass = String
|
29
|
+
klass.should_receive(:inspect).twice
|
30
|
+
schema = Membrane::Schema::Class.new(klass)
|
31
|
+
|
32
|
+
parser.deparse(schema).should == klass.inspect
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should deparse the k/v schemas of a Membrane::Schema::Dictionary schema" do
|
36
|
+
key_schema = Membrane::Schema::Class.new(String)
|
37
|
+
val_schema = Membrane::Schema::Class.new(Integer)
|
38
|
+
|
39
|
+
dict_schema = Membrane::Schema::Dictionary.new(key_schema, val_schema)
|
40
|
+
|
41
|
+
parser.deparse(dict_schema).should == "dict(String, Integer)"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should deparse the element schemas of a Membrane::Schema::Enum schema" do
|
45
|
+
schemas =
|
46
|
+
[String, Integer, Float].map { |c| Membrane::Schema::Class.new(c) }
|
47
|
+
|
48
|
+
enum_schema = Membrane::Schema::Enum.new(*schemas)
|
49
|
+
|
50
|
+
parser.deparse(enum_schema).should == "enum(String, Integer, Float)"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should deparse the element schema of a Membrane::Schema::List schema" do
|
54
|
+
key_schema = Membrane::Schema::Class.new(String)
|
55
|
+
val_schema = Membrane::Schema::Class.new(Integer)
|
56
|
+
item_schema = Membrane::Schema::Dictionary.new(key_schema, val_schema)
|
57
|
+
|
58
|
+
list_schema = Membrane::Schema::List.new(item_schema)
|
59
|
+
|
60
|
+
parser.deparse(list_schema).should == "[dict(String, Integer)]"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should deparse elem schemas of a Membrane::Schema::Record schema" do
|
64
|
+
str_schema = Membrane::Schema::Class.new(String)
|
65
|
+
int_schema = Membrane::Schema::Class.new(Integer)
|
66
|
+
dict_schema = Membrane::Schema::Dictionary.new(str_schema, int_schema)
|
67
|
+
|
68
|
+
int_rec_schema = Membrane::Schema::Record.new({:str => str_schema,
|
69
|
+
:dict => dict_schema})
|
70
|
+
|
71
|
+
rec_schema = Membrane::Schema::Record.new({"str" => str_schema,
|
72
|
+
"rec" => int_rec_schema,
|
73
|
+
"int" => int_schema})
|
74
|
+
exp_deparse =<<EOT
|
75
|
+
{
|
76
|
+
"str" => String,
|
77
|
+
"rec" => {
|
78
|
+
:str => String,
|
79
|
+
:dict => dict(String, Integer),
|
80
|
+
},
|
81
|
+
"int" => Integer,
|
82
|
+
}
|
83
|
+
EOT
|
84
|
+
parser.deparse(rec_schema).should == exp_deparse.strip
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should call inspect on regexps for Membrane::Schema::Regexp" do
|
88
|
+
schema = Membrane::Schema::Regexp.new(/test/)
|
89
|
+
schema.regexp.should_receive(:inspect)
|
90
|
+
parser.deparse(schema)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should deparse the element schemas of a Membrane::Schema::Tuple schema" do
|
94
|
+
schemas = [String, Integer].map { |c| Membrane::Schema::Class.new(c) }
|
95
|
+
schemas << Membrane::Schema::Value.new("test")
|
96
|
+
|
97
|
+
enum_schema = Membrane::Schema::Tuple.new(*schemas)
|
98
|
+
|
99
|
+
parser.deparse(enum_schema).should == 'tuple(String, Integer, "test")'
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should raise an error if given a non-schema" do
|
103
|
+
expect do
|
104
|
+
parser.deparse({})
|
105
|
+
end.to raise_error(ArgumentError, /Expected instance/)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "#parse" do
|
110
|
+
it "should leave instances derived from Membrane::Schema::Base unchanged" do
|
111
|
+
old_schema = Membrane::Schema::ANY
|
112
|
+
|
113
|
+
parser.parse { old_schema }.should == old_schema
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should translate 'any' into Membrane::Schema::Any" do
|
117
|
+
schema = parser.parse { any }
|
118
|
+
|
119
|
+
schema.class.should == Membrane::Schema::Any
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should translate 'bool' into Membrane::Schema::Bool" do
|
123
|
+
schema = parser.parse { bool }
|
124
|
+
|
125
|
+
schema.class.should == Membrane::Schema::Bool
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should translate 'enum' into Membrane::Schema::Enum" do
|
129
|
+
schema = parser.parse { enum(bool, any) }
|
130
|
+
|
131
|
+
schema.class.should == Membrane::Schema::Enum
|
132
|
+
|
133
|
+
schema.elem_schemas.length.should == 2
|
134
|
+
|
135
|
+
elem_schema_classes = schema.elem_schemas.map { |es| es.class }
|
136
|
+
|
137
|
+
expected_classes = [Membrane::Schema::Bool, Membrane::Schema::Any]
|
138
|
+
elem_schema_classes.should == expected_classes
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should translate 'dict' into Membrane::Schema::Dictionary" do
|
142
|
+
schema = parser.parse { dict(String, Integer) }
|
143
|
+
|
144
|
+
schema.class.should == Membrane::Schema::Dictionary
|
145
|
+
|
146
|
+
schema.key_schema.class.should == Membrane::Schema::Class
|
147
|
+
schema.key_schema.klass.should == String
|
148
|
+
|
149
|
+
schema.value_schema.class.should == Membrane::Schema::Class
|
150
|
+
schema.value_schema.klass.should == Integer
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should translate 'tuple' into Membrane::Schema::Tuple" do
|
154
|
+
schema = parser.parse { tuple(String, any, Integer) }
|
155
|
+
|
156
|
+
schema.class.should == Membrane::Schema::Tuple
|
157
|
+
|
158
|
+
schema.elem_schemas[0].class.should == Membrane::Schema::Class
|
159
|
+
schema.elem_schemas[0].klass.should == String
|
160
|
+
|
161
|
+
schema.elem_schemas[1].class == Membrane::Schema::Any
|
162
|
+
|
163
|
+
schema.elem_schemas[2].class.should == Membrane::Schema::Class
|
164
|
+
schema.elem_schemas[2].klass.should == Integer
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should translate classes into Membrane::Schema::Class" do
|
168
|
+
schema = parser.parse { String }
|
169
|
+
|
170
|
+
schema.class.should == Membrane::Schema::Class
|
171
|
+
|
172
|
+
schema.klass.should == String
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should translate regexps into Membrane::Schema::Regexp" do
|
176
|
+
regexp = /foo/
|
177
|
+
|
178
|
+
schema = parser.parse { regexp }
|
179
|
+
|
180
|
+
schema.class.should == Membrane::Schema::Regexp
|
181
|
+
|
182
|
+
schema.regexp.should == regexp
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should fall back to Membrane::Schema::Value" do
|
186
|
+
schema = parser.parse { 5 }
|
187
|
+
|
188
|
+
schema.class.should == Membrane::Schema::Value
|
189
|
+
schema.value.should == 5
|
190
|
+
end
|
191
|
+
|
192
|
+
describe "when parsing a list" do
|
193
|
+
it "should raise an error when no element schema is supplied" do
|
194
|
+
expect do
|
195
|
+
parser.parse { [] }
|
196
|
+
end.to raise_error(ArgumentError, /must supply/)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should raise an error when supplied > 1 element schema" do
|
200
|
+
expect do
|
201
|
+
parser.parse { [String, String] }
|
202
|
+
end.to raise_error(ArgumentError, /single schema/)
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should parse '[<expr>]' into Membrane::Schema::List" do
|
206
|
+
schema = parser.parse { [String] }
|
207
|
+
|
208
|
+
schema.class.should == Membrane::Schema::List
|
209
|
+
|
210
|
+
schema.elem_schema.class.should == Membrane::Schema::Class
|
211
|
+
schema.elem_schema.klass.should == String
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe "when parsing a record" do
|
216
|
+
it "should raise an error if the record is empty" do
|
217
|
+
expect do
|
218
|
+
parser.parse { {} }
|
219
|
+
end.to raise_error(ArgumentError, /must supply/)
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should parse '{ <key> => <schema> }' into Membrane::Schema::Record" do
|
223
|
+
schema = parser.parse do
|
224
|
+
{ "string" => String,
|
225
|
+
"ints" => [Integer],
|
226
|
+
}
|
227
|
+
end
|
228
|
+
|
229
|
+
schema.class.should == Membrane::Schema::Record
|
230
|
+
|
231
|
+
str_schema = schema.schemas["string"]
|
232
|
+
str_schema.class.should == Membrane::Schema::Class
|
233
|
+
str_schema.klass.should == String
|
234
|
+
|
235
|
+
ints_schema = schema.schemas["ints"]
|
236
|
+
ints_schema.class.should == Membrane::Schema::List
|
237
|
+
ints_schema.elem_schema.class.should == Membrane::Schema::Class
|
238
|
+
ints_schema.elem_schema.klass.should == Integer
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should handle keys marked with 'optional()'" do
|
242
|
+
schema = parser.parse { { optional("test") => Integer } }
|
243
|
+
|
244
|
+
schema.class.should == Membrane::Schema::Record
|
245
|
+
schema.optional_keys.to_a.should == ["test"]
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Membrane::Schema::Tuple do
|
4
|
+
let(:schema) do
|
5
|
+
Membrane::Schema::Tuple.new(Membrane::Schema::Class.new(String),
|
6
|
+
Membrane::Schema::ANY,
|
7
|
+
Membrane::Schema::Class.new(Integer))
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#validate" do
|
11
|
+
it "should raise an error if the validated object isn't an array" do
|
12
|
+
expect_validation_failure(schema, {}, /Array/)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should raise an error if the validated object has too many/few items" do
|
16
|
+
expect_validation_failure(schema, ["foo", 2], /element/)
|
17
|
+
expect_validation_failure(schema, ["foo", 2, "bar", 3], /element/)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should raise an error if any of the items do not validate" do
|
21
|
+
expect_validation_failure(schema, [5, 2, 0], /0 =>/)
|
22
|
+
expect_validation_failure(schema, ["foo", 2, "foo"], /2 =>/)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return nil when validation succeeds" do
|
26
|
+
schema.validate(["foo", "bar", 5]).should be_nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
|
4
|
+
describe Membrane::Schema::Value do
|
5
|
+
describe "#validate" do
|
6
|
+
let(:schema) { Membrane::Schema::Value.new("test") }
|
7
|
+
|
8
|
+
it "should return nil for values that are equal" do
|
9
|
+
schema.validate("test").should be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should return an error for values that are not equal" do
|
13
|
+
expect_validation_failure(schema, "tast", /Expected test/)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|