yes 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.ruby ADDED
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: "yes"
3
+ version: 0.0.1
4
+ title: "YES"
5
+ summary: YAML Easy Schema
6
+ description: YAML Easy Schemas it a straight-foward but powerful YPath-based schema format and validation program for YAML documents.
7
+ loadpath:
8
+ - lib
9
+ manifest: MANIFEST
10
+ requires:
11
+ - name: qed
12
+ version: 0+
13
+ group:
14
+ - test
15
+ - name: detroit
16
+ version: 0+
17
+ group:
18
+ - build
19
+ conflicts: []
20
+
21
+ replaces: []
22
+
23
+ engine_check: []
24
+
25
+ organization: RubyWorks
26
+ contact: transfire@gmail.com
27
+ created: 2011-06-21
28
+ copyright: Copyright (c) 2011 Thomas Sawyer
29
+ licenses:
30
+ - BSD-2-Clause
31
+ authors:
32
+ - Thomas Sawyer
33
+ maintainers: []
34
+
35
+ resources:
36
+ home: http://rubyworks.github.com/yes
37
+ work: http://github.com/rubyworks/yes
38
+ mail: http://groups.google.com/group/rubyworks-mailinglist
39
+ repositories:
40
+ public: git://github.com/rubyworks/yes.git
41
+ spec_version: 1.0.0
@@ -0,0 +1,8 @@
1
+ --output-dir doc/yard
2
+ --title YES
3
+ --protected
4
+ --private
5
+ lib/
6
+ -
7
+ [A-Z][A-Z]*
8
+ log/*.rdoc
@@ -0,0 +1,31 @@
1
+ = RELEASE HISTORY
2
+
3
+ == HEAD / 2011-07-02
4
+
5
+ Current Development (7rans)
6
+
7
+ Changes:
8
+
9
+ * 4 Test Enhancements
10
+
11
+ * Add test for RequiresValidation.
12
+ * Use Lint class, as YES is now a module.
13
+ * Move QED .rdoc files to .md files.
14
+ * Add required and count constraint tests.
15
+
16
+ * 13 General Enhancements
17
+
18
+ * Pass tree to validations and change Required to Requires.
19
+ * Add node shortcuts to NodeValidation class.
20
+ * Fix AbstractValidation#match_delta range comparisons.
21
+ * Rename yaml-yes executable to yes-lint.
22
+ * Refactored validation into individual validation classes.
23
+ * Rename range to count and add new constraints.
24
+ * Add exclusive and improved required validation.
25
+ * Output a generalized node representation.
26
+ * Add schema for yes itself.
27
+ * When node's #type_id is nil use #kind.
28
+ * Fix typo in README example.
29
+ * Clarify design in README.
30
+ * Initial commit.
31
+
@@ -0,0 +1,35 @@
1
+ = COPYRIGHT NOTICES
2
+
3
+ == YES
4
+
5
+ Copyright:: (c) 2011 Rubyworks, Thomas Sawyer
6
+ License:: BSD-2-Clause
7
+ Website:: http://rubyworks.github.com/yes
8
+
9
+ Copyright 2011 Thomas Sawyer. All rights reserved.
10
+
11
+ Redistribution and use in source and binary forms, with or without
12
+ modification, are permitted provided that the following conditions are met:
13
+
14
+ * Redistributions of source code must retain the above copyright notice,
15
+ this list of conditions and the following disclaimer.
16
+
17
+ * Redistributions in binary form must reproduce the above copyright notice,
18
+ this list of conditions and the following disclaimer in the documentation
19
+ and/or other materials provided with the distribution.
20
+
21
+ THIS SOFTWARE IS PROVIDED BY Thomas Sawyer ``AS IS'' AND ANY EXPRESS
22
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
24
+ NO EVENT SHALL Thomas Sawyer OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+
32
+ The views and conclusions contained in the software and documentation are
33
+ those of the authors and should not be interpreted as representing official
34
+ policies, either expressed or implied, of Thomas Sawyer.
35
+
@@ -0,0 +1,1036 @@
1
+ = Test Battery
2
+
3
+ The following is a long set of validation scenarios, each
4
+ consists of a schema followed by a set of YAML documents
5
+ that should or should not be valid under it.
6
+
7
+
8
+ ## Count Validation
9
+
10
+ Given a Schema:
11
+
12
+ ---
13
+ //foo:
14
+ count: 1
15
+
16
+ Then this YAML document is valid:
17
+
18
+ ---
19
+ foo: true
20
+
21
+ And this YAML document is valid:
22
+
23
+ ---
24
+ foo: true
25
+ bar: true
26
+
27
+ But this YAML document is not valid:
28
+
29
+ ---
30
+ - foo: true
31
+ - foo: true
32
+
33
+
34
+
35
+ ## Exclusive Constraints
36
+
37
+ As a reminder, exclusion can either be a boolean expression, in which case
38
+ it validates that there is no more than one matching node, or the value
39
+ is taken to be a YPath and validates that there are no matching paths
40
+ if the main selection is present.
41
+
42
+ ### Boolean Cases
43
+
44
+ Given a Schema:
45
+
46
+ ---
47
+ //foo:
48
+ exclusive: true
49
+
50
+ Then this YAML document is valid:
51
+
52
+ ---
53
+ - foo: true
54
+
55
+ And this YAML document is valid:
56
+
57
+ ---
58
+ - foo: true
59
+ - bar: true
60
+
61
+ But this YAML document is not valid:
62
+
63
+ ---
64
+ - foo: true
65
+ - foo: false
66
+
67
+ ### YPath Cases
68
+
69
+ Given a Schema:
70
+
71
+ ---
72
+ //foo:
73
+ exclusive: //bar
74
+
75
+ Then this YAML document is valid:
76
+
77
+ ---
78
+ - foo: true
79
+
80
+ But this YAML document is not valid:
81
+
82
+ ---
83
+ - foo: true
84
+ - bar: false
85
+
86
+
87
+ ## Inclusive Constraints
88
+
89
+ As a reminder, inclusion can either be a boolean expression,
90
+ in which case it validates that there is at least one matching
91
+ node, or the value is taken to be a ypath and validates that
92
+ there are matching paths if the main selection is present.
93
+
94
+ ### Boolean Cases
95
+
96
+ Given a Schema:
97
+
98
+ ---
99
+ //foo:
100
+ inclusive: true
101
+
102
+ Then this YAML document is valid:
103
+
104
+ ---
105
+ foo: true
106
+
107
+ And this YAML document is valid:
108
+
109
+ ---
110
+ foo: true
111
+ bar: true
112
+
113
+ But this YAML document is not valid:
114
+
115
+ ---
116
+ bar: true
117
+
118
+ ### YPath Cases
119
+
120
+ Given a Schema:
121
+
122
+ ---
123
+ //foo:
124
+ inclusive: //bar
125
+
126
+ Then this YAML document is valid:
127
+
128
+ ---
129
+ - foo: true
130
+ - bar: true
131
+
132
+
133
+
134
+ ## Tag Validation
135
+
136
+ Given a Schema:
137
+
138
+ ---
139
+ //name:
140
+ tag: "!<tag:yes.com,2011:name>"
141
+
142
+ Then this YAML document is valid:
143
+
144
+ ---
145
+ name: !!<tag:yes.com,2011:name> Choo Choo Train
146
+
147
+ And this YAML document is valid:
148
+
149
+ ---
150
+ - name: !!<tag:yes.com,2011:name> Choo Choo Train
151
+
152
+ But this YAML document is not valid:
153
+
154
+ ---
155
+ - name: Choo Choo Train
156
+
157
+
158
+
159
+ # Constraints
160
+
161
+
162
+ ## Tag Constraint
163
+
164
+ Given a schema with a `type` constraint:
165
+
166
+ ---
167
+ //name:
168
+ tag: '<tag:yes.com,2011:name>'
169
+
170
+ And a YAML document that has matching nodes:
171
+
172
+ ---
173
+ - name: !!<tag:yes.com,2011:name> Choo Choo Train
174
+
175
+ Then validation of the YAML document with the schema will
176
+ be valid and retun no validation errors.
177
+
178
+ yes = YES::Lint.new(@schema)
179
+ errors = yes.validate(@yaml)
180
+ errors.assert.empty?
181
+
182
+ If given a YAML document that lacks matching nodes:
183
+
184
+ ---
185
+ - name: Jar Jar Binks
186
+
187
+ Then the validation will return errors.
188
+
189
+ errors = yes.validate(@yaml)
190
+ errors.refute.empty?
191
+
192
+
193
+ ## Type Constraint
194
+
195
+ Given a schema with a `type` constraint:
196
+
197
+ ---
198
+ //foo:
199
+ type: str
200
+
201
+ And a YAML document that has matching nodes:
202
+
203
+ ---
204
+ - foo: I'm a string!
205
+
206
+ Then validation of the YAML document with the schema will
207
+ be valid and retun no validation errors.
208
+
209
+ yes = YES::Lint.new(@schema)
210
+ errors = yes.validate(@yaml)
211
+ errors.assert.empty?
212
+
213
+ If given a YAML document that lacks matching nodes:
214
+
215
+ ---
216
+ - foo: 15907
217
+
218
+ Then the validation will return errors.
219
+
220
+ errors = yes.validate(@yaml)
221
+ errors.refute.empty?
222
+
223
+
224
+ ## Requires Constraint
225
+
226
+ Given a schema with a `requires` constraint:
227
+
228
+ ---
229
+ /foo:
230
+ requires:
231
+ - bar
232
+
233
+ And a YAML document that has the required path:
234
+
235
+ ---
236
+ foo:
237
+ bar: true
238
+
239
+ Then validation of the YAML document with the schema will
240
+ ve valid and retun no validation errors.
241
+
242
+ yes = YES::Lint.new(@schema)
243
+ yes.validate(@yaml).assert.empty?
244
+
245
+ Given a YAML document that lacks the required path:
246
+
247
+ ---
248
+ foo: true
249
+
250
+ Then the validation will return errors.
251
+
252
+ errors = yes.validate(@yaml)
253
+ errors.refute.empty?
254
+
255
+ TODO: more detailed assertions on returned errors list.
256
+
257
+
258
+ ## Range Constraint
259
+
260
+ ### Fixed Range
261
+
262
+ Given a schema with a `range` constraint using a single value,
263
+ e.g. `1` then the range is equivalent to `1..1`:
264
+
265
+ ---
266
+ //foo:
267
+ range: 1
268
+
269
+ And a YAML document that has matching nodes:
270
+
271
+ ---
272
+ - foo: 1
273
+
274
+ Then validation of the YAML document with the schema will
275
+ ve valid and retun no validation errors.
276
+
277
+ yes = YES::Lint.new(@schema)
278
+ errors = yes.validate(@yaml)
279
+ errors.assert.empty?
280
+
281
+ If given a YAML document that lacks matching nodes:
282
+
283
+ ---
284
+ - foo: 2
285
+
286
+ Then the validation will return errors.
287
+
288
+ errors = yes.validate(@yaml)
289
+ errors.refute.empty?
290
+
291
+ ### Range
292
+
293
+ Given a schema with a `range` constraint using a fixed range:
294
+
295
+ ---
296
+ //foo:
297
+ range: 1..2
298
+
299
+ And a YAML document that has matching nodes:
300
+
301
+ ---
302
+ - foo: 1
303
+ - foo: 2
304
+
305
+ Then validation of the YAML document with the schema will
306
+ ve valid and retun no validation errors.
307
+
308
+ yes = YES::Lint.new(@schema)
309
+ errors = yes.validate(@yaml)
310
+ errors.assert.empty?
311
+
312
+ If given a YAML document that lacks matching nodes:
313
+
314
+ ---
315
+ - foo: 3
316
+
317
+ Then the validation will return errors.
318
+
319
+ errors = yes.validate(@yaml)
320
+ errors.refute.empty?
321
+
322
+ ### Range N
323
+
324
+ Given a schema with a `range` constraint using a range from a fixed number
325
+ to `n`, respesenting infinity:
326
+
327
+ ---
328
+ //foo:
329
+ range: 2..n
330
+
331
+ And a YAML document that has matching nodes:
332
+
333
+ ---
334
+ - foo: 2
335
+ - foo: 3
336
+
337
+ Then validation of the YAML document with the schema will
338
+ be valid and retun no validation errors.
339
+
340
+ yes = YES::Lint.new(@schema)
341
+ errors = yes.validate(@yaml)
342
+ errors.assert.empty?
343
+
344
+ If given a YAML document that lacks matching nodes:
345
+
346
+ ---
347
+ - foo: 1
348
+
349
+ Then the validation will return errors.
350
+
351
+ errors = yes.validate(@yaml)
352
+ errors.refute.empty?
353
+
354
+ TODO: more detailed assertions on returned errors list.
355
+
356
+
357
+ = Regular Expression Constraint
358
+
359
+ Becuase regular expresion engines can vary somewhat across implementations
360
+ it is wise to stick to the basics.
361
+
362
+ Given a schema with a `regexp` constraint:
363
+
364
+ ---
365
+ //email:
366
+ regexp: /@/
367
+
368
+ And a YAML document that has matching nodes:
369
+
370
+ ---
371
+ - email: foo@foo.net
372
+
373
+ Then validation of the YAML document with the schema will
374
+ be valid and retun no validation errors.
375
+
376
+ yes = YES::Lint.new(@schema)
377
+
378
+ errors = yes.validate(@yaml)
379
+ errors.assert.empty?
380
+
381
+ If given a YAML document that lacks matching nodes:
382
+
383
+ ---
384
+ - email: 15907
385
+
386
+ Then the validation will return errors.
387
+
388
+ errors = yes.validate(@yaml)
389
+ errors.refute.empty?
390
+
391
+
392
+ = File Name Constraint
393
+
394
+ Given a schema with a `fnmatch` constraint:
395
+
396
+ ---
397
+ //path:
398
+ fnmatch: "*.rb"
399
+
400
+ And a YAML document that has matching nodes:
401
+
402
+ ---
403
+ - email: foo.rb
404
+
405
+ Then validation of the YAML document with the schema will
406
+ be valid and retun no validation errors.
407
+
408
+ yes = YES::Lint.new(@schema)
409
+ errors = yes.validate(@yaml)
410
+ errors.assert.empty?
411
+
412
+ If given a YAML document that lacks matching nodes:
413
+
414
+ ---
415
+ - path: foo.txt
416
+
417
+ Then the validation will return errors.
418
+
419
+ errors = yes.validate(@yaml)
420
+ errors.refute.empty?
421
+
422
+
423
+ ## Length Constraint
424
+
425
+ ### Fixed Length
426
+
427
+ Given a schema with a `length` constraint using a single number:
428
+
429
+ ---
430
+ //foo:
431
+ length: 1
432
+
433
+ And a YAML document that has that number of nodes:
434
+
435
+ ---
436
+ - foo: "A"
437
+
438
+ Then validation of the YAML document with the schema will
439
+ ve valid and retun no validation errors.
440
+
441
+ yes = YES::Lint.new(@schema)
442
+ errors = yes.validate(@yaml)
443
+ errors.assert.empty?
444
+
445
+ If given a YAML document that lacks the right number of nodes:
446
+
447
+ ---
448
+ - foo: "AB"
449
+
450
+ Then the validation will return errors.
451
+
452
+ errors = yes.validate(@yaml)
453
+ errors.refute.empty?
454
+
455
+ ### Range
456
+
457
+ Given a schema with a `length` constraint using a fixed range:
458
+
459
+ ---
460
+ //foo:
461
+ length: 1..2
462
+
463
+ And a YAML document that has that range of nodes:
464
+
465
+ ---
466
+ - foo: "A"
467
+ - foo: "AB"
468
+
469
+ Then validation of the YAML document with the schema will
470
+ ve valid and retun no validation errors.
471
+
472
+ yes = YES::Lint.new(@schema)
473
+ errors = yes.validate(@yaml)
474
+ errors.assert.empty?
475
+
476
+ If given a YAML document that lacks the right number of nodes:
477
+
478
+ ---
479
+ - foo: ""
480
+ - foo: "ABC"
481
+
482
+ Then the validation will return errors.
483
+
484
+ errors = yes.validate(@yaml)
485
+ errors.refute.empty?
486
+
487
+ ### Range N
488
+
489
+ Given a schema with a `length` constraint using a range from a fixed number
490
+ to `n`, respesenting infinity:
491
+
492
+ ---
493
+ //foo:
494
+ length: 2..n
495
+
496
+ And a YAML document that has such a range of nodes:
497
+
498
+ ---
499
+ - foo: "AB"
500
+ - foo: "ABC"
501
+
502
+ Then validation of the YAML document with the schema will
503
+ be valid and retun no validation errors.
504
+
505
+ yes = YES::Lint.new(@schema)
506
+ errors = yes.validate(@yaml)
507
+ errors.assert.empty?
508
+
509
+ If given a YAML document that lacks the right number of nodes:
510
+
511
+ ---
512
+ - foo: "A"
513
+
514
+ Then the validation will return errors.
515
+
516
+ errors = yes.validate(@yaml)
517
+ errors.refute.empty?
518
+
519
+ TODO: more detailed assertions on returned errors list.
520
+
521
+
522
+ ## Count Constraint
523
+
524
+ ### Fixed Count
525
+
526
+ Given a schema with a `count` constraint using a single number:
527
+
528
+ ---
529
+ //foo:
530
+ count: 1
531
+
532
+ And a YAML document that has that number of nodes:
533
+
534
+ ---
535
+ - foo: true
536
+
537
+ Then validation of the YAML document with the schema will
538
+ ve valid and retun no validation errors.
539
+
540
+ yes = YES::Lint.new(@schema)
541
+ errors = yes.validate(@yaml)
542
+ errors.assert.empty?
543
+
544
+ If given a YAML document that lacks the right number of nodes:
545
+
546
+ ---
547
+ - foo: true
548
+ - foo: true
549
+
550
+ Then the validation will return errors.
551
+
552
+ errors = yes.validate(@yaml)
553
+ errors.refute.empty?
554
+
555
+ ### Range
556
+
557
+ Given a schema with a `count` constraint using a fixed range:
558
+
559
+ ---
560
+ //foo:
561
+ count: 1..2
562
+
563
+ And a YAML document that has that range of nodes:
564
+
565
+ ---
566
+ - foo: true
567
+
568
+ Then validation of the YAML document with the schema will
569
+ ve valid and retun no validation errors.
570
+
571
+ yes = YES::Lint.new(@schema)
572
+ errors = yes.validate(@yaml)
573
+ errors.assert.empty?
574
+
575
+ If given a YAML document that lacks the right number of nodes:
576
+
577
+ ---
578
+ - foo: true
579
+ - foo: true
580
+ - foo: true
581
+
582
+ Then the validation will return errors.
583
+
584
+ errors = yes.validate(@yaml)
585
+ errors.refute.empty?
586
+
587
+ ### Range N
588
+
589
+ Given a schema with a `count` constraint using a range from a fixed number
590
+ to `n`, respesenting infinity:
591
+
592
+ ---
593
+ //foo:
594
+ count: 2..n
595
+
596
+ And a YAML document that has such a range of nodes:
597
+
598
+ ---
599
+ - foo: true
600
+ - foo: true
601
+ - foo: true
602
+
603
+ Then validation of the YAML document with the schema will
604
+ be valid and retun no validation errors.
605
+
606
+ yes = YES::Lint.new(@schema)
607
+ errors = yes.validate(@yaml)
608
+ errors.assert.empty?
609
+
610
+ If given a YAML document that lacks the right number of nodes:
611
+
612
+ ---
613
+ - foo: true
614
+
615
+ Then the validation will return errors.
616
+
617
+ errors = yes.validate(@yaml)
618
+ errors.refute.empty?
619
+
620
+ TODO: more detailed assertions on returned errors list.
621
+
622
+
623
+ ## Inclusive Constraint
624
+
625
+ ### Boolean
626
+
627
+ Given a schema with an `inclusive` constraint using a boolean value:
628
+
629
+ ---
630
+ //foo:
631
+ inclusive: true
632
+
633
+ And a YAML document that has that includes a matching node:
634
+
635
+ ---
636
+ - foo: true
637
+
638
+ Then validation of the YAML document with the schema will
639
+ ve valid and retun no validation errors.
640
+
641
+ yes = YES::Lint.new(@schema)
642
+ errors = yes.validate(@yaml)
643
+ errors.assert.empty?
644
+
645
+ If given a YAML document that lacks a matching node:
646
+
647
+ ---
648
+ - bar: true
649
+ - baz: true
650
+
651
+ Then the validation will return errors.
652
+
653
+ errors = yes.validate(@yaml)
654
+ errors.refute.empty?
655
+
656
+ ### YPath
657
+
658
+ Given a schema with an `inclusive` constraint using a YPath value:
659
+
660
+ ---
661
+ //foo:
662
+ inclusive: //bar
663
+
664
+ And a YAML document that has that includes a matching node:
665
+
666
+ ---
667
+ - foo: true
668
+ - bar: true
669
+
670
+ Then validation of the YAML document with the schema will
671
+ ve valid and retun no validation errors.
672
+
673
+ yes = YES::Lint.new(@schema)
674
+ errors = yes.validate(@yaml)
675
+ errors.assert.empty?
676
+
677
+ If given a YAML document that lacks a matching node:
678
+
679
+ ---
680
+ - foo: true
681
+ - baz: true
682
+
683
+ Then the validation will return errors.
684
+
685
+ errors = yes.validate(@yaml)
686
+ errors.refute.empty?
687
+
688
+
689
+ ## Exclusive Constraint
690
+
691
+ ### Boolean
692
+
693
+ Given a schema with an `exclusive` constraint using a boolean value:
694
+
695
+ ---
696
+ //foo:
697
+ exclusive: true
698
+
699
+ And a YAML document that has that includes a matching node:
700
+
701
+ ---
702
+ - foo: true
703
+
704
+ Then validation of the YAML document with the schema will
705
+ ve valid and retun no validation errors.
706
+
707
+ yes = YES::Lint.new(@schema)
708
+ errors = yes.validate(@yaml)
709
+ errors.assert.empty?
710
+
711
+ If given a YAML document that lacks a matching node:
712
+
713
+ ---
714
+ - foo: true
715
+ - foo: true
716
+
717
+ Then the validation will return errors.
718
+
719
+ errors = yes.validate(@yaml)
720
+ errors.refute.empty?
721
+
722
+ ### YPath
723
+
724
+ Given a schema with an `exclusive` constraint using a YPath value:
725
+
726
+ ---
727
+ //foo:
728
+ exclusive: //bar
729
+
730
+ And a YAML document that has that includes a matching node:
731
+
732
+ ---
733
+ - foo: true
734
+ - gah: true
735
+
736
+ Then validation of the YAML document with the schema will
737
+ ve valid and retun no validation errors.
738
+
739
+ yes = YES::Lint.new(@schema)
740
+ errors = yes.validate(@yaml)
741
+ errors.assert.empty?
742
+
743
+ If given a YAML document that lacks a matching node:
744
+
745
+ ---
746
+ - foo: true
747
+ - bar: true
748
+
749
+ Then the validation will return errors.
750
+
751
+ errors = yes.validate(@yaml)
752
+ errors.refute.empty?
753
+
754
+ That covers the basics of exclusive constraints.
755
+ See here[../99_battery/exclusive_validations.md]
756
+ for an exhustive battery of tests.
757
+
758
+ ## Value Constraint
759
+
760
+ The value constraint differs from other constraints in that it
761
+ actually applies a separate set of constraints on the value
762
+ of a sequence's or mapping's elements.
763
+
764
+ Given a schema with an `valuee` constraint:
765
+
766
+ ---
767
+ //foo:
768
+ value:
769
+ type: str
770
+
771
+ And a YAML document that that includes a matching node:
772
+
773
+ ---
774
+ foo:
775
+ - "okay"
776
+
777
+ Then validation of the YAML document with the schema will
778
+ be valid and retun no validation errors.
779
+
780
+ yes = YES::Lint.new(@schema)
781
+ errors = yes.validate(@yaml)
782
+ errors.assert.empty?
783
+
784
+ If given a YAML document that lacks a matching node:
785
+
786
+ ---
787
+ foo:
788
+ - 0
789
+
790
+ Then the validation will return errors.
791
+
792
+ errors = yes.validate(@yaml)
793
+ errors.refute.empty?
794
+
795
+
796
+ ## Key Constraint
797
+
798
+ The key constraint differs from other constraints in that it
799
+ actually applies a separate set of constraints on the keys
800
+ of a mapping.
801
+
802
+ Given a schema with a `key` constraint:
803
+
804
+ ---
805
+ //foo:
806
+ key:
807
+ type: str
808
+
809
+ And a YAML document that that includes a matching node:
810
+
811
+ ---
812
+ foo:
813
+ bar: okay
814
+ baz: okay
815
+
816
+ Then validation of the YAML document with the schema will
817
+ be valid and retun no validation errors.
818
+
819
+ yes = YES::Lint.new(@schema)
820
+ errors = yes.validate(@yaml)
821
+ errors.assert.empty?
822
+
823
+ If given a YAML document that lacks a matching node:
824
+
825
+ ---
826
+ foo:
827
+ 0: "not okay"
828
+ 1: "not okay"
829
+
830
+ Then the validation will return errors.
831
+
832
+ errors = yes.validate(@yaml)
833
+ errors.refute.empty?
834
+
835
+
836
+ ## Required Constraint
837
+
838
+ Given a schema with a `required` constraint:
839
+
840
+ ---
841
+ //foo:
842
+ required: true
843
+
844
+ And a YAML document that hasthe required path:
845
+
846
+ ---
847
+ foo: true
848
+
849
+ Then validation of the YAML document with the schema will
850
+ ve valid and retun no validation errors.
851
+
852
+ yes = YES::Lint.new(@schema)
853
+ yes.validate(@yaml).assert.empty?
854
+
855
+ If given a YAML document that lacks the required path:
856
+
857
+ ---
858
+ bar: true
859
+
860
+ Then the validation will return errors.
861
+
862
+ errors = yes.validate(@yaml)
863
+ errors.refute.empty?
864
+
865
+ TODO: more detailed assertions on returned errors list.
866
+
867
+
868
+
869
+
870
+ ## Lint#select_nodes
871
+
872
+ The `select_nodes` method can take a YPath string or a complex selector.
873
+
874
+ A Complex selector is a mapping (i.e. a Ruby Hash) that uses node constraints
875
+ to select nodes from the document tree.
876
+
877
+ To try this out we need a Lint instance, which we will supply an empty, dummy
878
+ schema, as w won't be testing validation.
879
+
880
+ yes = YES::Lint.new('')
881
+
882
+ Given a YAML document:
883
+
884
+ ---
885
+ - Choo Choo Train
886
+ - Choo Choo Toy
887
+
888
+ Which we parse into a node tree.
889
+
890
+ tree = YAML.parse(@yaml)
891
+
892
+ A complex selector can be used to match nodes using the #select_nodes method.
893
+
894
+ complex_selector = { regexp: /^Choo/ }
895
+
896
+ selected = yes.select_nodes(complex_selector, tree)
897
+
898
+ selected.size.assert == 2
899
+
900
+
901
+ ## Sub-Selecting Nodes with Map Field
902
+
903
+ The `map` field, while appearing alongside constraint definitions
904
+ in the schema, is not actually a constraint, but rather a sub-ypath
905
+ selector that combines the parent ypath with the mapping keys
906
+ that are given under it. This provides a convenient way to keep
907
+ sub-paths local to their parent nodes, rather then create separate
908
+ long-name ypath entries. Obviously the `map` field only effectively
909
+ applies to mapping nodes.
910
+
911
+ Lets' take an example of the more explicit form:
912
+
913
+ ---
914
+ foo:
915
+ type: map
916
+ foo/bar:
917
+ type: str
918
+
919
+ This can be writ instead, Given a schema with a `map` field:
920
+
921
+ ---
922
+ foo:
923
+ type: map
924
+ map:
925
+ bar:
926
+ type: str
927
+
928
+ And a YAML document that includes a matching node:
929
+
930
+ ---
931
+ foo:
932
+ bar: okay
933
+
934
+ Then validation of the YAML document with the schema will
935
+ be valid and retun no validation errors.
936
+
937
+ yes = YES::Lint.new(@schema)
938
+ errors = yes.validate(@yaml)
939
+ errors.assert.empty?
940
+
941
+ If given a YAML document that lacks a matching node:
942
+
943
+ ---
944
+ foo:
945
+ bar: 0
946
+
947
+ Then the validation will return errors.
948
+
949
+ errors = yes.validate(@yaml)
950
+ errors.refute.empty?
951
+
952
+
953
+ ## Using a Complex Selector
954
+
955
+ Given a schema with a hash based selector:
956
+
957
+ ---
958
+ ? { regexp: /^Choo/ }
959
+ : { count: 2 }
960
+
961
+ And a YAML document that has matching nodes:
962
+
963
+ ---
964
+ - Choo Choo Train
965
+ - Choo Choo Toy
966
+
967
+ Then validation of the YAML document with the schema will
968
+ be valid and retun no validation errors.
969
+
970
+ yes = YES::Lint.new(@schema)
971
+
972
+ errors = yes.validate(@yaml)
973
+ errors.assert.empty?
974
+
975
+ If given a YAML document that lacks matching nodes:
976
+
977
+ ---
978
+ - Choo Choo Train
979
+
980
+ Then the validation will return errors.
981
+
982
+ errors = yes.validate(@yaml)
983
+ errors.refute.empty?
984
+
985
+
986
+ ## YPath Index
987
+
988
+ Given a YAML document:
989
+
990
+ ---
991
+ foo: "foo1"
992
+ bar:
993
+ foo: "foo2"
994
+ baz: "baz"
995
+
996
+ Lets let try out some YPaths.
997
+
998
+ s = @yaml.select('foo')
999
+
1000
+ s.size.assert == 1
1001
+
1002
+ s1 = s.first
1003
+ s1.value.assert == "foo1"
1004
+
1005
+ Try another
1006
+
1007
+ s = @yaml.select('//foo')
1008
+
1009
+ s.size.assert == 2
1010
+
1011
+ s1 = s.last
1012
+ s1.value.assert == "foo2"
1013
+
1014
+
1015
+ ## YPath by Tag
1016
+
1017
+ Given a YAML document:
1018
+
1019
+ ---
1020
+ foo: "foo1"
1021
+ bar: !example
1022
+ foo: "foo2"
1023
+ baz: "baz"
1024
+
1025
+ It would be nice if we could select nodes by tag, like:
1026
+
1027
+ s = @yaml.select('!example')
1028
+
1029
+ s.size.assert == 1
1030
+
1031
+ s1 = s.first
1032
+ s1.type.assert == "map"
1033
+
1034
+ But this does not work at this time.
1035
+
1036
+