data_bindings 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/test/bson_test.rb ADDED
@@ -0,0 +1,23 @@
1
+ require File.expand_path("../test_helper", __FILE__)
2
+
3
+ describe "Data Bindings bson" do
4
+ describe "bson parsing" do
5
+ it "should parse bson" do
6
+ a = DataBindings.from_bson(BSON.serialize(:author => 'siggy', :title => 'bible')).bind { property :author; property :title }
7
+ assert a.valid?
8
+ assert_equal "siggy", a[:author]
9
+ end
10
+ end
11
+
12
+ describe "bson generation" do
13
+ it "should generate bson" do
14
+ a = DataBindings.from_ruby('author' => 'siggy',"title" => 'koran').bind { property :author; property :title }
15
+ assert a.valid?
16
+ valid_bson_representations = [
17
+ "(\x00\x00\x00\x02author\x00\x06\x00\x00\x00siggy\x00\x02title\x00\x06\x00\x00\x00koran\x00\x00",
18
+ "(\x00\x00\x00\x02title\x00\x06\x00\x00\x00koran\x00\x02author\x00\x06\x00\x00\x00siggy\x00\x00"
19
+ ]
20
+ assert valid_bson_representations.include?( a.convert_to_bson )
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path("../test_helper", __FILE__)
2
+
3
+ describe "Data Bindings" do
4
+ before do
5
+ DataBindings.reset!
6
+ DataBindings.type(:person) do
7
+ property :name, String
8
+ property :age, Integer
9
+ end
10
+ end
11
+
12
+ describe "custom readers" do
13
+ it "should allow adding a custom converter" do
14
+ DataBindings.reader(:kolob) { '{"name":"god","age":123}' }
15
+ a = DataBindings.from_json_kolob.bind(:person)
16
+ assert_equal "god", a[:name]
17
+ assert a.valid?
18
+ end
19
+ end
20
+
21
+ describe "custom writers" do
22
+ it "should allow adding a custom converter" do
23
+ data = ''
24
+ DataBindings.writer(:kolob) { |o| data = o }
25
+ a = DataBindings.from_json('{"author":"siggy","title":"bible"}').convert_to_json_kolob
26
+ assert_equal MultiJson.decode('{"author":"siggy","title":"bible"}'), MultiJson.decode(data)
27
+ end
28
+
29
+ it "should allow adding a custom converter for a bound object" do
30
+ data = ''
31
+ DataBindings.writer(:kolob) { |o| data = o }
32
+ a = DataBindings.from_json('{"name":"siggy","age":32}').bind(:person).convert_to_json_kolob
33
+ assert_equal MultiJson.decode('{"name":"siggy","age":32}'), MultiJson.decode(data)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,67 @@
1
+ require File.expand_path("../test_helper", __FILE__)
2
+
3
+ describe "Data Bindings" do
4
+ before do
5
+ DataBindings.reset!
6
+ DataBindings.type(:person) do
7
+ property :name, String
8
+ property :age, Integer
9
+ end
10
+ end
11
+
12
+ it "should raise a validation error if neither the key or alias key exist on an object" do
13
+ DataBindings.type(:file) do
14
+ property :size, Integer
15
+ property :filename, String, :alias => [:filenames, :file_name]
16
+ end
17
+ a = DataBindings.from_json('{"size":925, "fn":"foo.txt"}').bind(:file)
18
+ assert_equal({'filename' => "not found"}, a.errors)
19
+ refute a.errors.empty?
20
+ refute a.valid?
21
+ end
22
+
23
+ describe "from_*_file" do
24
+ it "should load from a file" do
25
+ a = DataBindings.from_json_file(File.expand_path("../fixtures/1.json", __FILE__)).bind_array {
26
+ all_elements :person
27
+ }
28
+ assert a.valid?
29
+ assert_equal "josh", a[1][:name]
30
+ end
31
+ end
32
+
33
+ describe "from_*_net" do
34
+ it "should load from the net" do
35
+ a = DataBindings.from_json_http("http://localhost/1.json").bind_array {
36
+ all_elements :person
37
+ }
38
+ assert a.valid?
39
+ assert_equal "josh", a[1][:name]
40
+ end
41
+
42
+ it "should fail to load without auth" do
43
+ assert_raises DataBindings::HttpError do
44
+ a = DataBindings.from_json_http("http://secret/1.json").bind_array {
45
+ all_elements :person
46
+ }
47
+ end
48
+ end
49
+
50
+ it "should load with the right auth" do
51
+ a = DataBindings.from_json_http("http://secret/1.json", :basic_auth => {:username => 'test', :password => 'user'}).bind_array {
52
+ all_elements :person
53
+ }
54
+ assert a.valid?
55
+ assert_equal "josh", a[1][:name]
56
+ end
57
+ end
58
+
59
+ describe "strictness via the generator's default" do
60
+ it "should reject extra properties" do
61
+ DataBindings.strict = true
62
+ a = DataBindings.from_json('{"author":"siggy","title":"bible"}').bind { property :author }
63
+ assert_equal "siggy", a[:author]
64
+ refute a.valid?
65
+ end
66
+ end
67
+ end
@@ -0,0 +1 @@
1
+ [{"name":"andrew","age":32},{"name":"josh","age":12}]
data/test/json_test.rb ADDED
@@ -0,0 +1,40 @@
1
+ require File.expand_path("../test_helper", __FILE__)
2
+
3
+ describe "Data Bindings json" do
4
+ before do
5
+ DataBindings.reset!
6
+ DataBindings.type(:person) do
7
+ property :name, String
8
+ property :age, Integer
9
+ end
10
+ end
11
+
12
+ it "should create a JSON object" do
13
+ a = DataBindings.from_json('{"name":"Andrew","age":32}').bind(:person)
14
+ assert a.errors.empty?
15
+ assert a.valid?
16
+ assert_equal "Andrew", a[:name]
17
+ assert_equal MultiJson.decode("{\"name\":\"Andrew\",\"age\":32}"), MultiJson.decode(a.convert_to_json)
18
+ end
19
+
20
+ it "should refuse to create a JSON object when the data is invalid" do
21
+ a = DataBindings.from_json('{"name":"Andrew","age":"asd"}').bind(:person)
22
+ refute a.errors.empty?
23
+ refute a.valid?
24
+ assert_raises(DataBindings::FailedValidation) { a.convert_to_json }
25
+ end
26
+
27
+ it "should create a JSON object when the data is invalid and is forced" do
28
+ a = DataBindings.from_json('{"name":"Andrew","age":"asd"}').bind(:person)
29
+ refute a.errors.empty?
30
+ refute a.valid?
31
+ assert_equal MultiJson.decode("{\"name\":\"Andrew\",\"age\":\"asd\"}"), MultiJson.decode(a.force_convert_to_json)
32
+ end
33
+
34
+ it "should parse JSON" do
35
+ a = DataBindings.from_json("[1,2,3]").bind([Integer])
36
+ assert a.valid?
37
+ assert a.errors.empty?
38
+ assert_equal [1, 2, 3], [a[0], a[1], a[2]]
39
+ end
40
+ end
@@ -0,0 +1,64 @@
1
+ require File.expand_path("../test_helper", __FILE__)
2
+
3
+ describe "Data Bindings native" do
4
+ before do
5
+ DataBindings.reset!
6
+ DataBindings.type(:person) do
7
+ property :name, String
8
+ property :age, Integer
9
+ end
10
+ @person = Class.new { attr_accessor :name, :age; def initialize(name, age); @name, @age = name, age; end }
11
+ DataBindings.for_native(:person) { |props| @person.new(props[:name], props[:age]) }
12
+ end
13
+
14
+ it "should parse a Native object" do
15
+ p = @person.new("ben", 23)
16
+ a = DataBindings.from_native(p)
17
+ assert_equal "ben", a['name']
18
+ end
19
+
20
+ it "should transform into json without a binding (roughly)" do
21
+ p = @person.new("ben", 23)
22
+ assert_raises(DataBindings::UnboundError) { DataBindings.from_native(p).convert_to_json }
23
+ end
24
+
25
+ it "should not transform into json without a binding" do
26
+ p = @person.new("ben", 23)
27
+ a = DataBindings.from_native(p).bind(:person).convert_to_json
28
+ assert_equal({"name" => "ben", "age" => 23}, MultiJson.decode(a))
29
+ end
30
+
31
+ it "should transform into a native object" do
32
+ a = DataBindings.from_json('{"name":"Andrew","age":32}').bind(:person)
33
+ assert a.errors.empty?
34
+ assert a.valid?
35
+ assert_equal "Andrew", a[:name]
36
+ assert_equal "Andrew", a.to_native.name
37
+ end
38
+
39
+ it "should create a hash when there is no binding" do
40
+ a = DataBindings.from_json('{"name":"Andrew","age":32}').to_native
41
+ assert_equal "Andrew", a.name
42
+ end
43
+
44
+ it "should be able to create nested objets" do
45
+ DataBindings.type(:address_book) do
46
+ property :owner, :person
47
+ property :friends, [:person]
48
+ end
49
+ address_book = Class.new {
50
+ attr_accessor :owner, :friends
51
+ def initialize(owner, friends)
52
+ @owner, @friends = owner, friends
53
+ end
54
+
55
+ def find(name)
56
+ idx = @friends.find_index{|f| f.name == name }
57
+ idx && @friends[idx]
58
+ end
59
+ }
60
+ DataBindings.for_native(:address_book) { |props| address_book.new(props[:owner], props[:friends]) }
61
+ book = DataBindings.from_json('{"owner":{"name":"josh","age":34},"friends":[{"name":"grinch","age":123},{"name":"steve","age":23}]}').bind(:address_book).to_native
62
+ assert_equal 'steve', book.find('steve').name
63
+ end
64
+ end
@@ -0,0 +1,60 @@
1
+ require File.expand_path("../test_helper", __FILE__)
2
+
3
+ describe "Data Bindings params" do
4
+
5
+ describe "params parsing" do
6
+ it "should parse params" do
7
+ a = DataBindings.from_params("author=josh&title=great+expectations").bind { property :author; property :title }
8
+ assert a.valid?
9
+ assert_equal "josh", a[:author]
10
+ end
11
+
12
+ it "should parse a nested hash" do
13
+ a = DataBindings.from_params("name[first_name][short]=ben&name[first_name][long]=benjamin&name[last_name]=coe").bind { property :name }
14
+ assert a.valid?
15
+ assert_equal "ben", a[:name][:first_name][:short]
16
+ assert_equal "benjamin", a[:name][:first_name][:long]
17
+ assert_equal "coe", a[:name][:last_name]
18
+ end
19
+
20
+ it "should parse an array" do
21
+ a = DataBindings.from_params("name[0][last_name]=coe&name[0][first_name]=ben&name[1][first_name]=josh").bind { property :name }
22
+ assert a.valid?
23
+ assert_equal "ben", a[:name][0][:first_name]
24
+ assert_equal "coe", a[:name][0][:last_name]
25
+ assert_equal "josh", a[:name][1][:first_name]
26
+ end
27
+ end
28
+
29
+ describe "params generation" do
30
+
31
+ it "should generate params" do
32
+ a = DataBindings.from_ruby('author' => 'siggy',"title" => 'koran').bind { property :author; property :title }
33
+ assert a.valid?
34
+ assert_match "author=siggy", a.convert_to_params
35
+ end
36
+
37
+ it "should generate params for nested hash" do
38
+ a = DataBindings.from_ruby('author' => {'name' => {'first_name' => 'bill'}}, 'title' => 'koran', 'meta' => {'isbn' => 9999} ).bind do
39
+ property :author
40
+ property :title
41
+ property :meta
42
+ end
43
+ assert a.valid?
44
+ assert_match "author[name][first_name]=bill", a.convert_to_params
45
+ assert_match "meta[isbn]=9999", a.convert_to_params
46
+ assert_match "title=koran", a.convert_to_params
47
+ end
48
+
49
+ it "should generate params for nested array" do
50
+ a = DataBindings.from_ruby('authors' => ['josh', 'ben'], 'title' => 'koran' ).bind do
51
+ property :authors
52
+ property :title
53
+ end
54
+ assert a.valid?
55
+ assert_match "authors[0]=josh", a.convert_to_params
56
+ assert_match "title=koran", a.convert_to_params
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,17 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+
4
+ $: << File.expand_path("../../lib", __FILE__)
5
+ require 'data_bindings'
6
+ require 'fakeweb'
7
+
8
+ FakeWeb.allow_net_connect = false
9
+
10
+ Dir[File.expand_path("../fixtures/*", __FILE__)].each do |f|
11
+ FakeWeb.register_uri(:get, "http://localhost/#{File.basename(f)}", :body => File.read(f))
12
+ FakeWeb.register_uri(:get, "http://secret/#{File.basename(f)}", :body => "Unauthorized", :status => ["401", "Unauthorized"])
13
+ FakeWeb.register_uri(:get, "http://test:user@secret/#{File.basename(f)}", :body => File.read(f))
14
+ end
15
+
16
+ require 'bson'
17
+ require 'tnetstring'
@@ -0,0 +1,23 @@
1
+ require File.expand_path("../test_helper", __FILE__)
2
+
3
+ describe "Data Bindings tnetstring" do
4
+ describe "tnetstring parsing" do
5
+ it "should parse tnetstring" do
6
+ a = DataBindings.from_tnetstring(TNetstring.dump('author' => 'siggy', 'title' => 'bible')).bind { property :author; property :title }
7
+ assert a.valid?
8
+ assert_equal "siggy", a[:author]
9
+ end
10
+ end
11
+
12
+ describe "tnetstring generation" do
13
+ it "should generate tnetstring" do
14
+ a = DataBindings.from_ruby('author' => 'siggy',"title" => 'koran').bind { property :author; property :title }
15
+ assert a.valid?
16
+ valid_tnetstring_representations = [
17
+ "33:6:author,5:siggy,5:title,5:koran,}",
18
+ "33:5:title,5:koran,6:author,5:siggy,}"
19
+ ]
20
+ assert valid_tnetstring_representations.include?( a.convert_to_tnetstring )
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,217 @@
1
+ describe "Data Bindings validation" do
2
+ before do
3
+ DataBindings.reset!
4
+ end
5
+
6
+ it "should revalidate" do
7
+ a = DataBindings.from_json("[1,2,3]").bind([Integer])
8
+ assert a.valid?
9
+ assert a.errors.empty?
10
+ assert_equal [1, 2, 3], [a[0], a[1], a[2]]
11
+ a.unshift 'asd'
12
+ refute a.valid?
13
+ refute a.errors.empty?
14
+ end
15
+
16
+ it "should allow for a property to have a Boolean type" do
17
+ DataBindings.type(:person) do
18
+ property :name, String
19
+ property :awesome, :boolean
20
+ end
21
+ a = DataBindings.from_json('{"name":"Andrew","awesome":"true"}').bind(:person)
22
+ assert a.errors.empty?
23
+ assert a.valid?
24
+ assert_equal true, a[:awesome]
25
+ end
26
+
27
+ it "should allow for a property to have a default value set" do
28
+ DataBindings.type(:person) do
29
+ property :name, String
30
+ property :age, Integer, :default => 25
31
+ end
32
+ a = DataBindings.from_json('{"name":"Andrew"}').bind(:person)
33
+ assert a.errors.empty?
34
+ assert a.valid?
35
+ assert_equal 25, a[:age]
36
+ end
37
+
38
+ it "should allow the default value to be overridden with another value." do
39
+ DataBindings.type(:person) do
40
+ property :name, String
41
+ property :age, Integer, :default => 25
42
+ end
43
+ a = DataBindings.from_json('{"name":"Andrew", "age":26}').bind(:person)
44
+ assert a.errors.empty?
45
+ assert a.valid?
46
+ assert_equal 26, a[:age]
47
+ end
48
+
49
+ it "should allow for an alias property name to be set for a property" do
50
+ DataBindings.type(:file) do
51
+ property :size, Integer
52
+ property :filename, String, :alias => :file_name
53
+ end
54
+ a = DataBindings.from_json('{"size":925, "file_name":"foo.txt"}').bind(:file)
55
+ assert a.errors.empty?
56
+ assert a.valid?
57
+ assert_equal "foo.txt", a[:filename]
58
+ end
59
+
60
+ it "should allow an array of aliases to be provided for a property" do
61
+ DataBindings.type(:file) do
62
+ property :size, Integer
63
+ property :filename, String, :alias => [:filenames, :file_name]
64
+ end
65
+ a = DataBindings.from_json('{"size":925, "file_name":"foo.txt"}').bind(:file)
66
+ assert a.errors.empty?
67
+ assert a.valid?
68
+ assert_equal "foo.txt", a[:filename]
69
+ end
70
+
71
+ it "should raise when using bind! with invalid data" do
72
+ DataBindings.type(:person) do
73
+ property :name, String
74
+ property :age, Integer
75
+ end
76
+ assert_raises DataBindings::FailedValidation do
77
+ DataBindings.from_json('{"name":"Andrew","age":"asd"}').bind!(:person)
78
+ end
79
+ end
80
+
81
+ it "should give back the original object with errors with invalid data" do
82
+ DataBindings.type(:person) do
83
+ property :name, String
84
+ property :age, Integer
85
+ end
86
+ a = DataBindings.from_json('{"name":"Andrew","age":"asd"}').bind(:person)
87
+ assert_equal "Andrew", a[:name]
88
+ assert_equal "asd", a[:age]
89
+ refute a.valid?
90
+ end
91
+
92
+ describe "nested DataBindings::FailedValidation" do
93
+ before do
94
+ DataBindings.for_native(:person) { |obj| person.new(obj[:name], obj[:age]) }
95
+ DataBindings.type(:person) do
96
+ property :name, String
97
+ property :age, Integer
98
+ property :books, Array(:book)
99
+ end
100
+
101
+ DataBindings.type(:book) do
102
+ property :author, String
103
+ property :title, String
104
+ end
105
+ end
106
+
107
+ it "should bind to ruby" do
108
+ a = DataBindings.from_json('{"name":"Andrew","age":32,"books":[{"author":"Siggy","title":"Help Me"},{"author":"Samsum","title":"SC2 and you"}]}').bind(:person)
109
+ assert a.valid?
110
+ assert a.errors.empty?
111
+ assert_equal "Andrew", a[:name]
112
+ assert_equal "Help Me", a[:books][0][:title]
113
+ end
114
+
115
+ it "should be invalid if a nested object is invalid" do
116
+ a = DataBindings.from_json('{"name":"Andrew","age":32,"books":[{"author":"Siggy"},{"author":"Samsum","title":"SC2 and you"}]}').bind(:person)
117
+ refute a.valid?
118
+ refute a.errors.empty?
119
+ assert_equal "Andrew", a[:name]
120
+ assert_equal nil, a[:books][0][:title]
121
+ end
122
+ end
123
+
124
+ describe "nested validation" do
125
+ it "should bind to ruby" do
126
+ a = DataBindings.from_json('{"name":"Andrew","age":32,"book":{"author":"Siggy","title":"Help Me"}}').to_native
127
+ assert_equal OpenStruct, a.class
128
+ assert_equal "Siggy", a.book.author
129
+ end
130
+ end
131
+
132
+ describe "in clause" do
133
+ before do
134
+ DataBindings.type(:person) do
135
+ property :name, String, :in => %w(Steve John Andrew)
136
+ end
137
+ end
138
+
139
+ it "should have vaild data" do
140
+ a = DataBindings.from_json('{"name":"Andrew"}').bind(:person)
141
+ assert_equal "Andrew", a[:name]
142
+ assert a.valid?
143
+ end
144
+
145
+ it "should handle invaild data" do
146
+ a = DataBindings.from_json('{"name":"Josh"}').bind(:person)
147
+ assert_equal "Josh", a[:name]
148
+ refute a.valid?
149
+ end
150
+ end
151
+
152
+ describe "inline data type" do
153
+ before do
154
+ DataBindings.type(:person) do
155
+ property :books, [] do
156
+ property :author
157
+ property :title
158
+ end
159
+ end
160
+ end
161
+
162
+ it "should have vaild data" do
163
+ a = DataBindings.from_json('{"books":[{"author":"siggy","title":"bible"},{"author":"josh","title":"koran"}]}').bind(:person)
164
+ assert_equal "josh", a[:books][1][:author]
165
+ assert a.valid?
166
+ end
167
+
168
+ it "should handle invaild data" do
169
+ a = DataBindings.from_json('{"books":[{"author":"siggy"},{"author":"josh","title":"koran"}]}').bind(:person)
170
+ assert_equal "josh", a[:books][1][:author]
171
+ refute a.valid?
172
+ end
173
+
174
+ it "should allow binding to the data in a non-named way" do
175
+ a = DataBindings.from_json('{"books":[{"author":"siggy","title":"bible"},{"author":"josh","title":"koran"}]}').bind {
176
+ property :books, [] do
177
+ property :author
178
+ property :title
179
+ end
180
+ }
181
+ assert_equal "josh", a[:books][1][:author]
182
+ assert a.valid?
183
+ end
184
+ end
185
+
186
+ describe "ad-hoc data type" do
187
+ it "should allow binding to the data in a non-named way" do
188
+ a = DataBindings.from_json('{"books":[{"author":"siggy","title":"bible"},{"author":"josh","title":"koran"}]}').bind {
189
+ property :books, [] do
190
+ property :author
191
+ property :title
192
+ end
193
+ }
194
+ assert_equal "josh", a[:books][1][:author]
195
+ assert a.valid?
196
+ end
197
+
198
+ it "should handle invaild data" do
199
+ a = DataBindings.from_json('{"books":[{"author":"siggy"},{"author":"josh","title":"koran"}]}').bind {
200
+ property :books, [] do
201
+ property :author
202
+ property :title
203
+ end
204
+ }
205
+ assert_equal "josh", a[:books][1][:author]
206
+ refute a.valid?
207
+ end
208
+
209
+ describe "strictness" do
210
+ it "should reject extra properties" do
211
+ a = DataBindings.from_json('{"author":"siggy","title":"bible"}').bind(:strict => true) { property :author }
212
+ assert_equal "siggy", a[:author]
213
+ refute a.valid?
214
+ end
215
+ end
216
+ end
217
+ end