yes 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/.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
+