autoparse 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,904 @@
1
+ # Copyright 2010 Google Inc
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ spec_dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
17
+
18
+ require 'spec_helper'
19
+
20
+ require 'json'
21
+ require 'autoparse'
22
+ require 'addressable/uri'
23
+
24
+ describe AutoParse::Instance, 'with an empty schema' do
25
+ before do
26
+ @parser = AutoParse::EMPTY_SCHEMA
27
+ end
28
+
29
+ it 'should accept all inputs' do
30
+ instance = @parser.new({
31
+ "this" => "doesn't",
32
+ "really" => ["matter", "at", "all"],
33
+ "!" => 1.2345
34
+ })
35
+ instance.should be_valid
36
+ end
37
+
38
+ it 'should expose values via index methods' do
39
+ instance = @parser.new({
40
+ "this" => "doesn't",
41
+ "really" => ["matter", "at", "all"],
42
+ "!" => 1.2345
43
+ })
44
+ instance["this"].should == "doesn't"
45
+ instance["really"].should == ["matter", "at", "all"]
46
+ instance["!"].should == 1.2345
47
+ end
48
+
49
+ it 'should be coerceable to a Hash value' do
50
+ instance = @parser.new({
51
+ "this" => "doesn't",
52
+ "really" => ["matter", "at", "all"],
53
+ "!" => 1.2345
54
+ })
55
+ instance.to_hash.should == {
56
+ "this" => "doesn't",
57
+ "really" => ["matter", "at", "all"],
58
+ "!" => 1.2345
59
+ }
60
+ end
61
+
62
+ it 'should convert to a JSON string' do
63
+ instance = @parser.new({"be" => "brief"})
64
+ instance.to_json.should == '{"be":"brief"}'
65
+ end
66
+ end
67
+
68
+ describe AutoParse::Instance, 'with the geo schema' do
69
+ before do
70
+ @uri = Addressable::URI.new(
71
+ :scheme => 'file',
72
+ :host => '',
73
+ :path => File.expand_path(File.join(spec_dir, './data/geo.json'))
74
+ )
75
+ @schema_data = JSON.parse(File.open(@uri.path, 'r') { |f| f.read })
76
+ @parser = AutoParse.generate(@schema_data, @uri)
77
+ end
78
+
79
+ it 'should accept a valid geographic coordinate input' do
80
+ instance = @parser.new({
81
+ "latitude" => 37.422,
82
+ "longitude" => -122.084
83
+ })
84
+ instance.should be_valid
85
+ end
86
+
87
+ it 'should not accept an invalid geographic coordinate input' do
88
+ instance = @parser.new({
89
+ "latitude" => "not",
90
+ "longitude" => "valid"
91
+ })
92
+ instance.should_not be_valid
93
+ end
94
+
95
+ it 'should accept extra fields' do
96
+ instance = @parser.new({
97
+ "latitude" => 37.422,
98
+ "longitude" => -122.084,
99
+ "extra" => "bonus!"
100
+ })
101
+ instance.should be_valid
102
+ end
103
+
104
+ it 'should expose values via generated accessors' do
105
+ instance = @parser.new({
106
+ "latitude" => 37.422,
107
+ "longitude" => -122.084
108
+ })
109
+ instance.latitude.should == 37.422
110
+ instance.longitude.should == -122.084
111
+ end
112
+
113
+ it 'should be coerceable to a Hash value' do
114
+ instance = @parser.new({
115
+ "latitude" => 37.422,
116
+ "longitude" => -122.084
117
+ })
118
+ instance.to_hash.should == {
119
+ "latitude" => 37.422,
120
+ "longitude" => -122.084
121
+ }
122
+ end
123
+
124
+ it 'should convert to a JSON string' do
125
+ instance = @parser.new({
126
+ "latitude" => 37.422,
127
+ "longitude" => -122.084
128
+ })
129
+ instance.to_json.should == '{"latitude":37.422,"longitude":-122.084}'
130
+ end
131
+ end
132
+
133
+
134
+ describe AutoParse::Instance, 'with the address schema' do
135
+ before do
136
+ @uri = Addressable::URI.new(
137
+ :scheme => 'file',
138
+ :host => '',
139
+ :path => File.expand_path(File.join(spec_dir, './data/address.json'))
140
+ )
141
+ @schema_data = JSON.parse(File.open(@uri.path, 'r') { |f| f.read })
142
+ @parser = AutoParse.generate(@schema_data, @uri)
143
+ end
144
+
145
+ it 'should accept a valid address input' do
146
+ instance = @parser.new({
147
+ "post-office-box" => "PO Box 3.14159",
148
+ "street-address" => "1600 Amphitheatre Parkway",
149
+ "locality" => "Mountain View",
150
+ "region" => "CA",
151
+ "postal-code" => "94043",
152
+ "country-name" => "United States"
153
+ })
154
+ instance.should be_valid
155
+ end
156
+
157
+ it 'should accept extra fields' do
158
+ instance = @parser.new({
159
+ "post-office-box" => "PO Box 3.14159",
160
+ "street-address" => "1600 Amphitheatre Parkway",
161
+ "locality" => "Mountain View",
162
+ "region" => "CA",
163
+ "postal-code" => "94043",
164
+ "country-name" => "United States",
165
+ "extra" => "bonus!"
166
+ })
167
+ instance.should be_valid
168
+ end
169
+
170
+ it 'should accept a minimally valid address input' do
171
+ instance = @parser.new({
172
+ "locality" => "Mountain View",
173
+ "region" => "CA",
174
+ "country-name" => "United States"
175
+ })
176
+ instance.should be_valid
177
+ end
178
+
179
+ it 'should not accept an address with unmet dependencies' do
180
+ instance = @parser.new({
181
+ "post-office-box" => "PO Box 3.14159",
182
+ "extended-address" => "Apt 2.71828",
183
+ "locality" => "Mountain View",
184
+ "region" => "CA",
185
+ "country-name" => "United States"
186
+ })
187
+ instance.should_not be_valid
188
+ end
189
+
190
+ it 'should expose values via generated accessors' do
191
+ instance = @parser.new({
192
+ "post-office-box" => "PO Box 3.14159",
193
+ "street-address" => "1600 Amphitheatre Parkway",
194
+ "locality" => "Mountain View",
195
+ "region" => "CA",
196
+ "postal-code" => "94043",
197
+ "country-name" => "United States"
198
+ })
199
+ instance.post_office_box.should == "PO Box 3.14159"
200
+ instance.street_address.should == "1600 Amphitheatre Parkway"
201
+ instance.locality.should == "Mountain View"
202
+ instance.region.should == "CA"
203
+ instance.postal_code.should == "94043"
204
+ instance.country_name.should == "United States"
205
+ end
206
+
207
+ it 'should be coerceable to a Hash value' do
208
+ instance = @parser.new({
209
+ "post-office-box" => "PO Box 3.14159",
210
+ "street-address" => "1600 Amphitheatre Parkway",
211
+ "locality" => "Mountain View",
212
+ "region" => "CA",
213
+ "postal-code" => "94043",
214
+ "country-name" => "United States"
215
+ })
216
+ instance.to_hash.should == {
217
+ "post-office-box" => "PO Box 3.14159",
218
+ "street-address" => "1600 Amphitheatre Parkway",
219
+ "locality" => "Mountain View",
220
+ "region" => "CA",
221
+ "postal-code" => "94043",
222
+ "country-name" => "United States"
223
+ }
224
+ end
225
+ end
226
+
227
+ describe AutoParse::Instance, 'with the person schema' do
228
+ before do
229
+ @uri = Addressable::URI.new(
230
+ :scheme => 'file',
231
+ :host => '',
232
+ :path => File.expand_path(File.join(spec_dir, './data/person.json'))
233
+ )
234
+ @schema_data = JSON.parse(File.open(@uri.path, 'r') { |f| f.read })
235
+ @parser = AutoParse.generate(@schema_data, @uri)
236
+ end
237
+
238
+ it 'should accept a valid person input' do
239
+ instance = @parser.new({
240
+ "name" => "Bob Aman",
241
+ "age" => 29
242
+ })
243
+ instance.should be_valid
244
+ end
245
+
246
+ it 'should accept extra fields' do
247
+ instance = @parser.new({
248
+ "name" => "Bob Aman",
249
+ "age" => 29,
250
+ "extra" => "bonus!"
251
+ })
252
+ instance.should be_valid
253
+ end
254
+
255
+ it 'should validate a person whose age is equal to the maximum' do
256
+ instance = @parser.new({
257
+ "name" => "Aged Outlier",
258
+ "age" => 125
259
+ })
260
+ instance.should be_valid
261
+ end
262
+
263
+ it 'should validate a young person' do
264
+ instance = @parser.new({
265
+ "name" => "Joe Teenager",
266
+ "age" => 15
267
+ })
268
+ instance.should be_valid
269
+ end
270
+
271
+ it 'should not accept an invalid person input' do
272
+ instance = @parser.new({
273
+ "name" => "Methuselah",
274
+ "age" => 969
275
+ })
276
+ instance.should_not be_valid
277
+ end
278
+
279
+ it 'should not accept ages which are not integers' do
280
+ instance = @parser.new({
281
+ "name" => "Bob Aman",
282
+ "age" => 29.7
283
+ })
284
+ instance.should_not be_valid
285
+ end
286
+
287
+ it 'should expose values via generated accessors' do
288
+ instance = @parser.new({
289
+ "name" => "Bob Aman",
290
+ "age" => 29
291
+ })
292
+ instance.name.should == "Bob Aman"
293
+ instance.age.should == 29
294
+ end
295
+
296
+ it 'should be coerceable to a Hash value' do
297
+ instance = @parser.new({
298
+ "name" => "Bob Aman",
299
+ "age" => 29
300
+ })
301
+ instance.to_hash.should == {
302
+ "name" => "Bob Aman",
303
+ "age" => 29
304
+ }
305
+ end
306
+
307
+ it 'should convert to a JSON string' do
308
+ instance = @parser.new({
309
+ "name" => "Bob Aman",
310
+ "age" => 29
311
+ })
312
+ instance.to_json.should == '{"name":"Bob Aman","age":29}'
313
+ end
314
+ end
315
+
316
+ describe AutoParse::Instance, 'with the adult schema' do
317
+ before do
318
+ @person_uri = Addressable::URI.new(
319
+ :scheme => 'file',
320
+ :host => '',
321
+ :path => File.expand_path(File.join(spec_dir, './data/person.json'))
322
+ )
323
+ @person_schema_data =
324
+ JSON.parse(File.open(@person_uri.path, 'r') { |f| f.read })
325
+ @person_parser = AutoParse.generate(@person_schema_data, @person_uri)
326
+
327
+ @adult_uri = Addressable::URI.new(
328
+ :scheme => 'file',
329
+ :host => '',
330
+ :path => File.expand_path(File.join(spec_dir, './data/adult.json'))
331
+ )
332
+ @adult_schema_data =
333
+ JSON.parse(File.open(@adult_uri.path, 'r') { |f| f.read })
334
+ @adult_parser = AutoParse.generate(@adult_schema_data, @adult_uri)
335
+ end
336
+
337
+ it 'should accept a valid person input' do
338
+ instance = @adult_parser.new({
339
+ "name" => "Bob Aman",
340
+ "age" => 29
341
+ })
342
+ instance.should be_valid
343
+ end
344
+
345
+ it 'should accept extra fields' do
346
+ instance = @adult_parser.new({
347
+ "name" => "Bob Aman",
348
+ "age" => 29,
349
+ "extra" => "bonus!"
350
+ })
351
+ instance.should be_valid
352
+ end
353
+
354
+ it 'should validate a person whose age is equal to the maximum' do
355
+ instance = @adult_parser.new({
356
+ "name" => "Aged Outlier",
357
+ "age" => 125
358
+ })
359
+ instance.should be_valid
360
+ end
361
+
362
+ it 'should not validate a young person' do
363
+ instance = @adult_parser.new({
364
+ "name" => "Joe Teenager",
365
+ "age" => 15
366
+ })
367
+ instance.should_not be_valid
368
+ end
369
+
370
+ it 'should not accept an invalid person input' do
371
+ instance = @adult_parser.new({
372
+ "name" => "Methuselah",
373
+ "age" => 969
374
+ })
375
+ instance.should_not be_valid
376
+ end
377
+
378
+ it 'should not accept ages which are not integers' do
379
+ instance = @adult_parser.new({
380
+ "name" => "Bob Aman",
381
+ "age" => 29.7
382
+ })
383
+ instance.should_not be_valid
384
+ end
385
+
386
+ it 'should expose values via generated accessors' do
387
+ instance = @adult_parser.new({
388
+ "name" => "Bob Aman",
389
+ "age" => 29
390
+ })
391
+ instance.name.should == "Bob Aman"
392
+ instance.age.should == 29
393
+ end
394
+
395
+ it 'should be coerceable to a Hash value' do
396
+ instance = @adult_parser.new({
397
+ "name" => "Bob Aman",
398
+ "age" => 29
399
+ })
400
+ instance.to_hash.should == {
401
+ "name" => "Bob Aman",
402
+ "age" => 29
403
+ }
404
+ end
405
+
406
+ it 'should convert to a JSON string' do
407
+ instance = @adult_parser.new({
408
+ "name" => "Bob Aman",
409
+ "age" => 29
410
+ })
411
+ instance.to_json.should == '{"name":"Bob Aman","age":29}'
412
+ end
413
+ end
414
+
415
+ describe AutoParse::Instance, 'with the positive schema' do
416
+ before do
417
+ @positive_uri = Addressable::URI.new(
418
+ :scheme => 'file',
419
+ :host => '',
420
+ :path => File.expand_path(File.join(spec_dir, './data/positive.json'))
421
+ )
422
+ @positive_schema_data =
423
+ JSON.parse(File.open(@positive_uri.path, 'r') { |f| f.read })
424
+ @positive_parser = AutoParse.generate(@positive_schema_data, @positive_uri)
425
+ end
426
+
427
+ it 'should not allow instantiation' do
428
+ (lambda do
429
+ instance = @positive_parser.new(-1000)
430
+ end).should raise_error(TypeError)
431
+ end
432
+
433
+ it 'should not allow instantiation, even for a valid positive integer' do
434
+ (lambda do
435
+ instance = @positive_parser.new(1000)
436
+ end).should raise_error(TypeError)
437
+ end
438
+ end
439
+
440
+ describe AutoParse::Instance, 'with the account schema' do
441
+ before do
442
+ @positive_uri = Addressable::URI.new(
443
+ :scheme => 'file',
444
+ :host => '',
445
+ :path => File.expand_path(File.join(spec_dir, './data/positive.json'))
446
+ )
447
+ @positive_schema_data =
448
+ JSON.parse(File.open(@positive_uri.path, 'r') { |f| f.read })
449
+ @positive_parser = AutoParse.generate(@positive_schema_data, @positive_uri)
450
+
451
+ @account_uri = Addressable::URI.new(
452
+ :scheme => 'file',
453
+ :host => '',
454
+ :path => File.expand_path(File.join(spec_dir, './data/account.json'))
455
+ )
456
+ @account_schema_data =
457
+ JSON.parse(File.open(@account_uri.path, 'r') { |f| f.read })
458
+ @account_parser = AutoParse.generate(@account_schema_data, @account_uri)
459
+ end
460
+
461
+ it 'should accept a valid account input' do
462
+ instance = @account_parser.new({
463
+ "accountNumber" => "12345",
464
+ "balance" => 1000
465
+ })
466
+ instance.should be_valid
467
+ end
468
+
469
+ it 'should accept extra fields' do
470
+ instance = @account_parser.new({
471
+ "accountNumber" => "12345",
472
+ "balance" => 1000,
473
+ "extra" => "bonus!"
474
+ })
475
+ instance.should be_valid
476
+ end
477
+
478
+ it 'should validate an account with a zero balance' do
479
+ instance = @account_parser.new({
480
+ "accountNumber" => "12345",
481
+ "balance" => 0
482
+ })
483
+ instance.should be_valid
484
+ end
485
+
486
+ it 'should not validate a negative account balance' do
487
+ instance = @account_parser.new({
488
+ "accountNumber" => "12345",
489
+ "balance" => -1000
490
+ })
491
+ instance.should_not be_valid
492
+ end
493
+
494
+ it 'should not accept an invalid account input' do
495
+ instance = @account_parser.new({
496
+ "accountNumber" => "12345",
497
+ "balance" => "bogus"
498
+ })
499
+ instance.should_not be_valid
500
+ end
501
+
502
+ it 'should expose values via generated accessors' do
503
+ instance = @account_parser.new({
504
+ "accountNumber" => "12345",
505
+ "balance" => 1000
506
+ })
507
+ instance.account_number.should == "12345"
508
+ instance.balance.should == 1000
509
+ end
510
+
511
+ it 'should be coerceable to a Hash value' do
512
+ instance = @account_parser.new({
513
+ "accountNumber" => "12345",
514
+ "balance" => 1000
515
+ })
516
+ instance.to_hash.should == {
517
+ "accountNumber" => "12345",
518
+ "balance" => 1000
519
+ }
520
+ end
521
+
522
+ it 'should convert to a JSON string' do
523
+ instance = @account_parser.new({
524
+ "accountNumber" => "12345",
525
+ "balance" => 1000
526
+ })
527
+ instance.to_json.should == '{"accountNumber":"12345","balance":1000}'
528
+ end
529
+ end
530
+
531
+ describe AutoParse::Instance, 'with the card schema' do
532
+ before do
533
+ @address_uri = Addressable::URI.new(
534
+ :scheme => 'file',
535
+ :host => '',
536
+ :path => File.expand_path(File.join(spec_dir, './data/address.json'))
537
+ )
538
+ @address_schema_data =
539
+ JSON.parse(File.open(@address_uri.path, 'r') { |f| f.read })
540
+ @address_parser = AutoParse.generate(@address_schema_data, @address_uri)
541
+
542
+ @geo_uri = Addressable::URI.new(
543
+ :scheme => 'file',
544
+ :host => '',
545
+ :path => File.expand_path(File.join(spec_dir, './data/geo.json'))
546
+ )
547
+ @geo_schema_data =
548
+ JSON.parse(File.open(@geo_uri.path, 'r') { |f| f.read })
549
+ @geo_parser = AutoParse.generate(@geo_schema_data, @geo_uri)
550
+
551
+ @card_uri = Addressable::URI.new(
552
+ :scheme => 'file',
553
+ :host => '',
554
+ :path => File.expand_path(File.join(spec_dir, './data/card.json'))
555
+ )
556
+ @card_schema_data =
557
+ JSON.parse(File.open(@card_uri.path, 'r') { |f| f.read })
558
+ @card_parser = AutoParse.generate(@card_schema_data, @card_uri)
559
+ end
560
+
561
+ it 'should accept a valid card input' do
562
+ instance = @card_parser.new({
563
+ "givenName" => "Robert",
564
+ "familyName" => "Aman"
565
+ })
566
+ instance.should be_valid
567
+ end
568
+
569
+ it 'should accept extra fields' do
570
+ instance = @card_parser.new({
571
+ "givenName" => "Robert",
572
+ "familyName" => "Aman",
573
+ "extra" => "bonus!"
574
+ })
575
+ instance.should be_valid
576
+ end
577
+
578
+ it 'should accept a more complete card input' do
579
+ instance = @card_parser.new({
580
+ "givenName" => "Robert",
581
+ "familyName" => "Aman",
582
+ "additionalName" => ["Danger"],
583
+ "nickname" => "Bob",
584
+ "url" => "https://plus.google.com/116452824309856782163",
585
+ "email" => {
586
+ "type" => "work",
587
+ "value" => "bobaman@google.com"
588
+ },
589
+ "tel" => {
590
+ "type" => "fake",
591
+ "value" => "867-5309"
592
+ },
593
+ "tz" => "+03:00",
594
+ "logo" =>
595
+ "https://secure.gravatar.com/avatar/56ee28134dd0776825445e3551979b14",
596
+ "org" => {
597
+ "organizationName" => "Google, Inc.",
598
+ "organizationUnit" => "Developer Relations"
599
+ }
600
+ })
601
+ instance.should be_valid
602
+ end
603
+
604
+ it 'should accept a card input with an externally referenced schema' do
605
+ instance = @card_parser.new({
606
+ "givenName" => "Robert",
607
+ "familyName" => "Aman",
608
+ "adr" => {
609
+ "locality" => "Lavington",
610
+ "region" => "Nairobi",
611
+ "country-name" => "Kenya"
612
+ },
613
+ "geo" => {
614
+ "latitude" => -1.290034,
615
+ "longitude" => 36.771584
616
+ }
617
+ })
618
+ instance.adr.should be_valid
619
+ instance.geo.should be_valid
620
+ instance.should be_valid
621
+ end
622
+
623
+ it 'should not validate a card input with invalid array values' do
624
+ instance = @card_parser.new({
625
+ "givenName" => "Robert",
626
+ "familyName" => "Aman",
627
+ "additionalName" => [3.14159]
628
+ })
629
+ instance.should_not be_valid
630
+ end
631
+
632
+ it 'should not validate a card input when external schema is invalid' do
633
+ instance = @card_parser.new({
634
+ "givenName" => "Robert",
635
+ "familyName" => "Aman",
636
+ "adr" => {
637
+ "extended-address" => "Apt 2.71828",
638
+ "locality" => "Lavington",
639
+ "region" => "Nairobi",
640
+ "country-name" => "Kenya"
641
+ },
642
+ "geo" => {
643
+ "latitude" => -1.290034,
644
+ "longitude" => 36.771584
645
+ }
646
+ })
647
+ instance.adr.should_not be_valid
648
+ instance.should_not be_valid
649
+ instance = @card_parser.new({
650
+ "givenName" => "Robert",
651
+ "familyName" => "Aman",
652
+ "adr" => {
653
+ "locality" => "Lavington",
654
+ "region" => "Nairobi",
655
+ "country-name" => "Kenya"
656
+ },
657
+ "geo" => {
658
+ "latitude" => "not",
659
+ "longitude" => "valid"
660
+ }
661
+ })
662
+ instance.geo.should_not be_valid
663
+ instance.should_not be_valid
664
+ end
665
+
666
+ it 'should expose values via generated accessors' do
667
+ instance = @card_parser.new({
668
+ "givenName" => "Robert",
669
+ "familyName" => "Aman",
670
+ "additionalName" => ["Danger"],
671
+ "nickname" => "Bob",
672
+ "url" => "https://plus.google.com/116452824309856782163",
673
+ "email" => {
674
+ "type" => "work",
675
+ "value" => "bobaman@google.com"
676
+ },
677
+ "tel" => {
678
+ "type" => "fake",
679
+ "value" => "867-5309"
680
+ },
681
+ "tz" => "+03:00",
682
+ "logo" =>
683
+ "https://secure.gravatar.com/avatar/56ee28134dd0776825445e3551979b14",
684
+ "org" => {
685
+ "organizationName" => "Google, Inc.",
686
+ "organizationUnit" => "Developer Relations"
687
+ }
688
+ })
689
+ instance.given_name.should == "Robert"
690
+ instance.family_name.should == "Aman"
691
+ instance.additional_name.should == ["Danger"]
692
+ instance.nickname.should == "Bob"
693
+ instance.url.should be_kind_of(Addressable::URI)
694
+ instance.url.should === "https://plus.google.com/116452824309856782163"
695
+ instance.email.type.should == "work"
696
+ instance.email.value.should == "bobaman@google.com"
697
+ instance.tel.type.should == "fake"
698
+ instance.tel.value.should == "867-5309"
699
+ instance.tz.should == "+03:00"
700
+ instance.logo.should ==
701
+ "https://secure.gravatar.com/avatar/56ee28134dd0776825445e3551979b14"
702
+ instance.org.organization_name.should == "Google, Inc."
703
+ instance.org.organization_unit.should == "Developer Relations"
704
+ end
705
+
706
+ it 'should be coerceable to a Hash value' do
707
+ instance = @card_parser.new({
708
+ "givenName" => "Robert",
709
+ "familyName" => "Aman",
710
+ "additionalName" => ["Danger"],
711
+ "nickname" => "Bob",
712
+ "url" => "https://plus.google.com/116452824309856782163",
713
+ "email" => {
714
+ "type" => "work",
715
+ "value" => "bobaman@google.com"
716
+ },
717
+ "tel" => {
718
+ "type" => "fake",
719
+ "value" => "867-5309"
720
+ },
721
+ "tz" => "+03:00",
722
+ "logo" =>
723
+ "https://secure.gravatar.com/avatar/56ee28134dd0776825445e3551979b14",
724
+ "org" => {
725
+ "organizationName" => "Google, Inc.",
726
+ "organizationUnit" => "Developer Relations"
727
+ }
728
+ })
729
+ instance.to_hash.should == {
730
+ "givenName" => "Robert",
731
+ "familyName" => "Aman",
732
+ "additionalName" => ["Danger"],
733
+ "nickname" => "Bob",
734
+ "url" => "https://plus.google.com/116452824309856782163",
735
+ "email" => {
736
+ "type" => "work",
737
+ "value" => "bobaman@google.com"
738
+ },
739
+ "tel" => {
740
+ "type" => "fake",
741
+ "value" => "867-5309"
742
+ },
743
+ "tz" => "+03:00",
744
+ "logo" =>
745
+ "https://secure.gravatar.com/avatar/56ee28134dd0776825445e3551979b14",
746
+ "org" => {
747
+ "organizationName" => "Google, Inc.",
748
+ "organizationUnit" => "Developer Relations"
749
+ }
750
+ }
751
+ end
752
+
753
+ it 'should convert to a JSON string' do
754
+ instance = @card_parser.new({
755
+ "givenName" => "Robert",
756
+ "familyName" => "Aman"
757
+ })
758
+ instance.to_json.should == '{"givenName":"Robert","familyName":"Aman"}'
759
+ end
760
+ end
761
+
762
+ describe AutoParse::Instance, 'with the calendar schema' do
763
+ before do
764
+ @geo_uri = Addressable::URI.new(
765
+ :scheme => 'file',
766
+ :host => '',
767
+ :path => File.expand_path(File.join(spec_dir, './data/geo.json'))
768
+ )
769
+ @geo_schema_data =
770
+ JSON.parse(File.open(@geo_uri.path, 'r') { |f| f.read })
771
+ @geo_parser = AutoParse.generate(@geo_schema_data, @geo_uri)
772
+
773
+ @calendar_uri = Addressable::URI.new(
774
+ :scheme => 'file',
775
+ :host => '',
776
+ :path => File.expand_path(File.join(spec_dir, './data/calendar.json'))
777
+ )
778
+ @calendar_schema_data =
779
+ JSON.parse(File.open(@calendar_uri.path, 'r') { |f| f.read })
780
+ @calendar_parser = AutoParse.generate(@calendar_schema_data, @calendar_uri)
781
+ end
782
+
783
+ it 'should accept a valid calendar input' do
784
+ instance = @calendar_parser.new({
785
+ "dtstart" => "1592-03-14T00:00:00Z",
786
+ "dtend" => "1592-03-14T23:59:59Z",
787
+ "summary" => "Pi Day",
788
+ "location" => "Googleplex",
789
+ "url" => "http://www.piday.org/",
790
+ "rrule" => "FREQ=YEARLY"
791
+ })
792
+ instance.should be_valid
793
+ end
794
+
795
+ it 'should accept extra fields' do
796
+ instance = @calendar_parser.new({
797
+ "dtstart" => "1592-03-14T00:00:00Z",
798
+ "dtend" => "1592-03-14T23:59:59Z",
799
+ "summary" => "Pi Day",
800
+ "location" => "Googleplex",
801
+ "url" => "http://www.piday.org/",
802
+ "rrule" => "FREQ=YEARLY",
803
+ "extra" => "bonus!"
804
+ })
805
+ instance.should be_valid
806
+ end
807
+
808
+ it 'should accept a calendar input with an externally referenced schema' do
809
+ instance = @calendar_parser.new({
810
+ "dtstart" => "1592-03-14T00:00:00Z",
811
+ "dtend" => "1592-03-14T23:59:59Z",
812
+ "summary" => "Pi Day",
813
+ "location" => "Googleplex",
814
+ "url" => "http://www.piday.org/",
815
+ "rrule" => "FREQ=YEARLY",
816
+ "geo" => {
817
+ "latitude" => 37.422,
818
+ "longitude" => -122.084
819
+ }
820
+ })
821
+ instance.geo.should be_valid
822
+ instance.should be_valid
823
+ end
824
+
825
+ it 'should not validate a calendar input when external schema is invalid' do
826
+ instance = @calendar_parser.new({
827
+ "dtstart" => "1592-03-14T00:00:00Z",
828
+ "dtend" => "1592-03-14T23:59:59Z",
829
+ "summary" => "Pi Day",
830
+ "location" => "Googleplex",
831
+ "url" => "http://www.piday.org/",
832
+ "rrule" => "FREQ=YEARLY",
833
+ "geo" => {
834
+ "latitude" => "not",
835
+ "longitude" => "valid"
836
+ }
837
+ })
838
+ instance.geo.should_not be_valid
839
+ instance.should_not be_valid
840
+ end
841
+
842
+ it 'should expose values via generated accessors' do
843
+ instance = @calendar_parser.new({
844
+ "dtstart" => "1592-03-14T00:00:00Z",
845
+ "dtend" => "1592-03-14T23:59:59Z",
846
+ "summary" => "Pi Day",
847
+ "location" => "Googleplex",
848
+ "url" => "http://www.piday.org/",
849
+ "rrule" => "FREQ=YEARLY",
850
+ "geo" => {
851
+ "latitude" => 37.422,
852
+ "longitude" => -122.084
853
+ }
854
+ })
855
+ instance.dtstart.should == Time.utc(1592, 3, 14)
856
+ instance.dtend.should == Time.utc(1592, 3, 14, 23, 59, 59)
857
+ instance.summary.should == "Pi Day"
858
+ instance.location.should == "Googleplex"
859
+ instance.url.should == Addressable::URI.parse("http://www.piday.org/")
860
+ instance.rrule.should == "FREQ=YEARLY"
861
+ instance.geo.latitude.should == 37.422
862
+ instance.geo.longitude.should == -122.084
863
+ end
864
+
865
+ it 'should be coerceable to a Hash value' do
866
+ instance = @calendar_parser.new({
867
+ "dtstart" => "1592-03-14T00:00:00Z",
868
+ "dtend" => "1592-03-14T23:59:59Z",
869
+ "summary" => "Pi Day",
870
+ "location" => "Googleplex",
871
+ "url" => "http://www.piday.org/",
872
+ "rrule" => "FREQ=YEARLY",
873
+ "geo" => {
874
+ "latitude" => 37.422,
875
+ "longitude" => -122.084
876
+ }
877
+ })
878
+ instance.to_hash.should == {
879
+ "dtstart" => "1592-03-14T00:00:00Z",
880
+ "dtend" => "1592-03-14T23:59:59Z",
881
+ "summary" => "Pi Day",
882
+ "location" => "Googleplex",
883
+ "url" => "http://www.piday.org/",
884
+ "rrule" => "FREQ=YEARLY",
885
+ "geo" => {
886
+ "latitude" => 37.422,
887
+ "longitude" => -122.084
888
+ }
889
+ }
890
+ end
891
+
892
+ it 'should convert to a JSON string' do
893
+ instance = @calendar_parser.new({
894
+ "dtstart" => "1592-03-14T00:00:00Z",
895
+ "dtend" => "1592-03-14T23:59:59Z",
896
+ "summary" => "Pi Day"
897
+ })
898
+ instance.to_json.should == (
899
+ '{"dtend":"1592-03-14T23:59:59Z",' +
900
+ '"dtstart":"1592-03-14T00:00:00Z",'+
901
+ '"summary":"Pi Day"}'
902
+ )
903
+ end
904
+ end