json-spec 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +960 -0
  7. data/Rakefile +10 -0
  8. data/api_documentation.md +611 -0
  9. data/cachivache/.gitignore +1 -0
  10. data/cachivache/Gemfile +4 -0
  11. data/cachivache/README.md +247 -0
  12. data/cachivache/Rakefile +19 -0
  13. data/cachivache/Vagrantfile +70 -0
  14. data/cachivache/cachivache.rb +59 -0
  15. data/cachivache/lib/let-behaviour.rb +27 -0
  16. data/cachivache/lib/rake-helper.rb +131 -0
  17. data/cachivache/lib/sh-file-context.rb +39 -0
  18. data/cachivache/lib/sh-if-context.rb +31 -0
  19. data/cachivache/stuff/.gitkeep +0 -0
  20. data/cachivache/stuff/ruby-json-spec.rb +22 -0
  21. data/examples/example-1-simple.rb +66 -0
  22. data/examples/example-2-default-expectations.rb +63 -0
  23. data/examples/example-3-each-field.rb +104 -0
  24. data/examples/example-4-to-be-as-defined-in.rb +117 -0
  25. data/examples/example-5-custom-expectations.rb +153 -0
  26. data/examples/example-6-custom-messages.rb +36 -0
  27. data/examples/example-7-full-example.rb +231 -0
  28. data/examples/fixtures.rb +77 -0
  29. data/examples/validation-printer.rb +47 -0
  30. data/json-spec.gemspec +29 -0
  31. data/lib/cabeza-de-termo/json-spec/errors/error.rb +6 -0
  32. data/lib/cabeza-de-termo/json-spec/errors/expectation-not-found-error.rb +8 -0
  33. data/lib/cabeza-de-termo/json-spec/errors/modifier-not-found-error.rb +8 -0
  34. data/lib/cabeza-de-termo/json-spec/errors/unkown-json-type-error.rb +8 -0
  35. data/lib/cabeza-de-termo/json-spec/errors/validation-error.rb +8 -0
  36. data/lib/cabeza-de-termo/json-spec/expectations-library/default-expectations/default-expectation-builder.rb +29 -0
  37. data/lib/cabeza-de-termo/json-spec/expectations-library/default-expectations/default-expectations-mapping.rb +54 -0
  38. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/block-expectation-definition.rb +16 -0
  39. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/class-expectation-definition.rb +15 -0
  40. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expectation-definition.rb +19 -0
  41. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expectations-definition-builder.rb +136 -0
  42. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expecting-all-of-expectation-definition.rb +23 -0
  43. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expecting-any-of-expectation-definition.rb +23 -0
  44. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expecting-expectation-definition.rb +17 -0
  45. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/negating-expectation-definition.rb +16 -0
  46. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-library-definition-builder.rb +35 -0
  47. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/class-modifier-definition.rb +15 -0
  48. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/composing-modifiers-definition.rb +28 -0
  49. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/modifier-definition.rb +13 -0
  50. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/modifiers-definition-builder.rb +73 -0
  51. data/lib/cabeza-de-termo/json-spec/expectations-library/expectations-library.rb +150 -0
  52. data/lib/cabeza-de-termo/json-spec/expectations-library/initializers/default-library-initializer.rb +265 -0
  53. data/lib/cabeza-de-termo/json-spec/expectations-library/initializers/library-initializer.rb +9 -0
  54. data/lib/cabeza-de-termo/json-spec/expectations-library/messages/expectation-messages-mapping.rb +27 -0
  55. data/lib/cabeza-de-termo/json-spec/expectations/abstract-expectation.rb +39 -0
  56. data/lib/cabeza-de-termo/json-spec/expectations/all-expectations-composite.rb +33 -0
  57. data/lib/cabeza-de-termo/json-spec/expectations/any-expectation-composite.rb +33 -0
  58. data/lib/cabeza-de-termo/json-spec/expectations/block-expectation.rb +28 -0
  59. data/lib/cabeza-de-termo/json-spec/expectations/expectation.rb +51 -0
  60. data/lib/cabeza-de-termo/json-spec/expectations/is-email-expectation.rb +16 -0
  61. data/lib/cabeza-de-termo/json-spec/expectations/is-scalar-expectation.rb +17 -0
  62. data/lib/cabeza-de-termo/json-spec/expectations/is-url-expectation.rb +21 -0
  63. data/lib/cabeza-de-termo/json-spec/expectations/negated-expectation.rb +31 -0
  64. data/lib/cabeza-de-termo/json-spec/expectations/runner/abstract-expectations-runner.rb +27 -0
  65. data/lib/cabeza-de-termo/json-spec/expectations/runner/can-be-absent-expectations-runner.rb +50 -0
  66. data/lib/cabeza-de-termo/json-spec/expectations/runner/can-be-null-expectations-runner.rb +48 -0
  67. data/lib/cabeza-de-termo/json-spec/expectations/runner/expectations-runner.rb +43 -0
  68. data/lib/cabeza-de-termo/json-spec/expressions/json-any-of.rb +62 -0
  69. data/lib/cabeza-de-termo/json-spec/expressions/json-anything.rb +16 -0
  70. data/lib/cabeza-de-termo/json-spec/expressions/json-each-field.rb +58 -0
  71. data/lib/cabeza-de-termo/json-spec/expressions/json-each.rb +58 -0
  72. data/lib/cabeza-de-termo/json-spec/expressions/json-expression.rb +314 -0
  73. data/lib/cabeza-de-termo/json-spec/expressions/json-field-name.rb +16 -0
  74. data/lib/cabeza-de-termo/json-spec/expressions/json-field.rb +76 -0
  75. data/lib/cabeza-de-termo/json-spec/expressions/json-list.rb +40 -0
  76. data/lib/cabeza-de-termo/json-spec/expressions/json-object.rb +82 -0
  77. data/lib/cabeza-de-termo/json-spec/expressions/json-scalar.rb +20 -0
  78. data/lib/cabeza-de-termo/json-spec/expressions/json-spec.rb +174 -0
  79. data/lib/cabeza-de-termo/json-spec/instantiators/abstract-instantiator.rb +9 -0
  80. data/lib/cabeza-de-termo/json-spec/instantiators/all-expectations-composite-instantiator.rb +12 -0
  81. data/lib/cabeza-de-termo/json-spec/instantiators/any-expectation-composite-instantiator.rb +12 -0
  82. data/lib/cabeza-de-termo/json-spec/instantiators/block-expectation-instantiator.rb +16 -0
  83. data/lib/cabeza-de-termo/json-spec/instantiators/composite-instantiator.rb +45 -0
  84. data/lib/cabeza-de-termo/json-spec/instantiators/modifier-composite-instantiator.rb +12 -0
  85. data/lib/cabeza-de-termo/json-spec/instantiators/negated-expectation-instantiator.rb +20 -0
  86. data/lib/cabeza-de-termo/json-spec/instantiators/patial-application-instantiator.rb +26 -0
  87. data/lib/cabeza-de-termo/json-spec/json-spec.rb +2 -0
  88. data/lib/cabeza-de-termo/json-spec/message-formatters/block-message-formatter.rb +15 -0
  89. data/lib/cabeza-de-termo/json-spec/message-formatters/erb-message-formatter.rb +60 -0
  90. data/lib/cabeza-de-termo/json-spec/message-formatters/message-formatter.rb +9 -0
  91. data/lib/cabeza-de-termo/json-spec/metaprogramming/message-send.rb +37 -0
  92. data/lib/cabeza-de-termo/json-spec/metaprogramming/message.rb +37 -0
  93. data/lib/cabeza-de-termo/json-spec/metaprogramming/object-method.rb +14 -0
  94. data/lib/cabeza-de-termo/json-spec/modifiers/can-be-absent-modifier.rb +13 -0
  95. data/lib/cabeza-de-termo/json-spec/modifiers/can-be-null-modifier.rb +13 -0
  96. data/lib/cabeza-de-termo/json-spec/modifiers/expression-modifier.rb +9 -0
  97. data/lib/cabeza-de-termo/json-spec/modifiers/modifier-composite.rb +27 -0
  98. data/lib/cabeza-de-termo/json-spec/signals/signal.rb +6 -0
  99. data/lib/cabeza-de-termo/json-spec/signals/skip-branch-signal.rb +8 -0
  100. data/lib/cabeza-de-termo/json-spec/utilities/bind.rb +20 -0
  101. data/lib/cabeza-de-termo/json-spec/utilities/range.rb +70 -0
  102. data/lib/cabeza-de-termo/json-spec/value-holders/accessors-chain.rb +27 -0
  103. data/lib/cabeza-de-termo/json-spec/value-holders/missing-value.rb +21 -0
  104. data/lib/cabeza-de-termo/json-spec/value-holders/value-holder.rb +135 -0
  105. data/lib/cabeza-de-termo/json-spec/version.rb +5 -0
  106. data/lib/cabeza-de-termo/json-spec/walkers/expression-walker.rb +66 -0
  107. data/lib/cabeza-de-termo/json-spec/walkers/json-expectations-runner.rb +214 -0
  108. data/lib/cabeza-de-termo/json-spec/walkers/json-expression-explainer.rb +183 -0
  109. data/lib/cabeza-de-termo/json-spec/walkers/reporter/expectation-report.rb +63 -0
  110. data/lib/cabeza-de-termo/json-spec/walkers/reporter/json-expectations-reporter.rb +111 -0
  111. data/lib/cabeza-de-termo/json-spec/walkers/validator/json-validator-error.rb +29 -0
  112. data/lib/cabeza-de-termo/json-spec/walkers/validator/json-validator.rb +133 -0
  113. data/lib/cabeza-de-termo/json-spec/walkers/value-holders-stack-behaviour.rb +57 -0
  114. metadata +242 -0
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "spec"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['spec/**/*-spec.rb']
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,611 @@
1
+ # API
2
+
3
+ ## Expressions on the root json expression
4
+
5
+ ### expect_an(:object)
6
+
7
+ Expects a root object.
8
+
9
+ ```ruby
10
+ expect_an(:object) do
11
+ ...
12
+ end
13
+ ```
14
+
15
+ Example of expected json:
16
+
17
+ ```json
18
+ {}
19
+ ```
20
+
21
+ ### expect_a(:list)
22
+
23
+ Expects a root list.
24
+
25
+ ```ruby
26
+ expect_a(:list) do
27
+ ...
28
+ end
29
+ ```
30
+
31
+ Example of expected json:
32
+
33
+ ```json
34
+ []
35
+ ```
36
+
37
+ ### expect(:any_of)
38
+
39
+ Expects one among many possible different root expressions.
40
+
41
+ ```ruby
42
+ expect(:any_of)
43
+ ...
44
+ or_also()
45
+ ...
46
+ or_also()
47
+ ...
48
+ end
49
+ ```
50
+
51
+ Example of expected json:
52
+
53
+ ```json
54
+ {}
55
+ or
56
+ []
57
+ ```
58
+
59
+ ## Expressions on an json object
60
+
61
+ ### expect(field_name) .to_be_a(:scalar)
62
+
63
+ Expects a scalar on a field named field_name
64
+
65
+ ```ruby
66
+ expect('id') .to_be_a(:scalar)
67
+ ```
68
+
69
+ Example of expected json:
70
+
71
+ ```json
72
+ {
73
+ "id": 123
74
+ }
75
+ ```
76
+
77
+ ### expect(field_name) .to_be_an(:object)
78
+
79
+ Expects an object on a field named field_name
80
+
81
+ ```ruby
82
+ expect('user') .to_be_an(:object) do
83
+ end
84
+ ```
85
+
86
+ Example of expected json:
87
+
88
+ ```json
89
+ {
90
+ "user": {
91
+ ...
92
+ }
93
+ }
94
+ ```
95
+
96
+ ### expect(field_name) .to_be_a(:list)
97
+
98
+ Expects a list on a field named field_name
99
+
100
+ ```ruby
101
+ expect(field_name) .to_be_a(:list) do
102
+ each do
103
+ ...
104
+ end
105
+ end
106
+ ```
107
+
108
+ Example of expected json:
109
+
110
+ ```json
111
+ {
112
+ "users": [
113
+ ...
114
+ ]
115
+ }
116
+ ```
117
+
118
+ ### expect(field_name) .to_be(:any_of)
119
+
120
+ Expects one among many possible different expressions on a field named field_name
121
+
122
+ ```ruby
123
+ expect('object_or_list') .to_be(:any_of) do
124
+ expect_an(:object) do
125
+ ...
126
+ end
127
+ or_also
128
+ expect_a(:list) do
129
+ ...
130
+ end
131
+ end
132
+ ```
133
+
134
+ Example of expected json:
135
+
136
+ ```json
137
+ {
138
+ "object_or_list": {
139
+ ...
140
+ }
141
+ or
142
+ "object_or_list": [
143
+ ...
144
+ ]
145
+ }
146
+ ```
147
+
148
+ ### each_field
149
+
150
+ Expects a name and an expression on every field of the object
151
+
152
+ ```ruby
153
+ each_field
154
+ expect_name
155
+
156
+ # one of the following expressions
157
+
158
+ expect(:anything)
159
+ # or
160
+ expect_a(:scalar)
161
+ # or
162
+ expect_an(:object) do
163
+ ...
164
+ end
165
+ # or
166
+ expect_a(:list) do
167
+ ...
168
+ end
169
+ # or
170
+ expect(:any_of) do
171
+ ...
172
+ or_also
173
+ ...
174
+ end
175
+ end
176
+ ```
177
+
178
+ Example of expected json:
179
+
180
+ ```json
181
+ {
182
+ "id": 123
183
+ or
184
+ "id": []
185
+ or
186
+ "name": 123
187
+ or
188
+ "name": []
189
+ etc
190
+ }
191
+ ```
192
+
193
+ ### expect(field_name) .to_be(:anything)
194
+
195
+ Expects anything scalar on a field named field_name
196
+
197
+ ```ruby
198
+ expect('name') .to_be(:anything)
199
+ ```
200
+
201
+ Example of expected json:
202
+
203
+ ```json
204
+ {
205
+ "name": "cabeza de termo"
206
+ }
207
+ ```
208
+
209
+ ## Expressions on an json list
210
+
211
+ ### expect_a(:scalar)
212
+
213
+ Expects a scalar on each item of a list
214
+
215
+ ```ruby
216
+ json_list do
217
+ each do
218
+ expect_a(:scalar)
219
+ end
220
+ end
221
+ ```
222
+
223
+ Example of expected json:
224
+
225
+ ```json
226
+ [
227
+ 123
228
+ ]
229
+ ```
230
+
231
+ ### expect_an(:object)
232
+
233
+ Expects an object on each item of a list
234
+
235
+ ```ruby
236
+ json_list do
237
+ each do
238
+ expect_an(:object) do
239
+ ...
240
+ end
241
+ end
242
+ end
243
+ ```
244
+
245
+ Example of expected json:
246
+
247
+ ```json
248
+ [
249
+ {
250
+ ...
251
+ }
252
+ ]
253
+ ```
254
+
255
+ ### expect_a(:list)
256
+
257
+ Expects a list on each item of a list
258
+
259
+ ```ruby
260
+ json_list do
261
+ each do
262
+ expect_a(:list) do
263
+ ...
264
+ end
265
+ end
266
+ end
267
+ ```
268
+
269
+ Example of expected json:
270
+
271
+ ```json
272
+ [
273
+ [
274
+ ...
275
+ ]
276
+ ]
277
+ ```
278
+
279
+ ### expect(:any_of)
280
+
281
+ Expects one among many possible different expressions on each item of a list
282
+
283
+ ```ruby
284
+ json_list do
285
+ each do
286
+ expect(:any_of)
287
+ expect_an(:object) do
288
+ ...
289
+ end
290
+ or_also
291
+ expect_a(:list)
292
+ ...
293
+ end
294
+ end
295
+ end
296
+ end
297
+ ```
298
+
299
+ Example of expected json:
300
+
301
+ ```json
302
+ [
303
+ {
304
+ ...
305
+ }
306
+ or
307
+ [
308
+ ...
309
+ ]
310
+ ]
311
+ ```
312
+
313
+ ## Library expectations
314
+
315
+ ### .to_exist
316
+
317
+ Expects an expression to be present.
318
+
319
+ ```ruby
320
+ expect(...) .to_exist
321
+ ```
322
+
323
+ ### .to_be_absent
324
+
325
+ Expects an expression not to be present.
326
+
327
+ ```ruby
328
+ expect(...) .to_be_absent
329
+ ```
330
+
331
+ ### .to_be_boolean
332
+
333
+ Expects a value to be a boolean.
334
+
335
+ ```ruby
336
+ expect(...) .to_be_boolean
337
+ ```
338
+
339
+ ### .to_be_float
340
+
341
+ Expects a value to be a float.
342
+
343
+ ```ruby
344
+ expect(...) .to_be_float
345
+ ```
346
+
347
+ ### .to_be_integer
348
+
349
+ Expects a value to be an integer.
350
+
351
+ ```ruby
352
+ expect(...) .to_be_integer
353
+ ```
354
+
355
+ ### .to_be_list
356
+
357
+ Expects a value to be a list.
358
+
359
+ ```ruby
360
+ expect(...) .to_be_list
361
+ ```
362
+
363
+ ### .to_be_number
364
+
365
+ Expects a value to be an integer or a double.
366
+
367
+ ```ruby
368
+ expect(...) .to_be_number
369
+ ```
370
+
371
+ ### .to_be_scalar
372
+
373
+ Expects a value to be a number, string, boolean or null.
374
+
375
+ ```ruby
376
+ expect(...) .to_be_scalar
377
+ ```
378
+
379
+ ### .to_be_object
380
+
381
+ Expects a value to be an object.
382
+
383
+ ```ruby
384
+ expect(...) .to_be_object
385
+ ```
386
+
387
+ ### .to_be_string
388
+
389
+ Expects a value to be a string.
390
+
391
+ ```ruby
392
+ expect(...) .to_be_string
393
+ ```
394
+
395
+ ### .to_be_null
396
+
397
+ Expects a value to be null.
398
+
399
+ ```ruby
400
+ expect(...) .to_be_null
401
+ ```
402
+
403
+ ### .not_null
404
+
405
+ Expects a value not to be null.
406
+
407
+ ```ruby
408
+ expect(...) .not_null
409
+ ```
410
+
411
+ ### .to_be_defined
412
+
413
+ Expects a field to be present and be not null.
414
+
415
+ ```ruby
416
+ expect(...) .to_be_defined
417
+ ```
418
+
419
+ ### .not_defined
420
+
421
+ Expects a value to be null or to be absent.
422
+
423
+ ```ruby
424
+ expect(...) .not_defined
425
+ ```
426
+
427
+ ### .to_be_empty
428
+
429
+ - If the value is an object, expects the object to have no fields
430
+ - If the value is a list, expects the list to have no items
431
+ - If the value is a string, expects the string to be == ''
432
+ - For any other type, raises an error
433
+
434
+ ```ruby
435
+ expect(...) .to_be_empty
436
+ ```
437
+
438
+ ### .not_empty
439
+
440
+ - If the value is an object, expects the object to have at least one field
441
+ - If the value is a list, expects the list to have at least one item
442
+ - If the value is a string, expects the string to have at least one character
443
+ - For any other type, raises an error
444
+
445
+ ```ruby
446
+ expect(...) .not_empty
447
+ ```
448
+
449
+ ### .to_be_blank
450
+
451
+ Expects a value to be blank. Blank means having no printable characters, event if its not empty.
452
+
453
+ ```ruby
454
+ expect(...) .to_be_blank
455
+ ```
456
+
457
+ ### .not_blank
458
+
459
+ Expects a value not to be blank. Not blank means having at least one printable character.
460
+
461
+ ```ruby
462
+ expect(...) .not_blank
463
+ ```
464
+
465
+ ### .to_be_equal_to(expected_value)
466
+
467
+ Expects a value to be equal to the expected_value.
468
+
469
+ ```ruby
470
+ expect(...) ..to_be_equal_to(42)
471
+ ```
472
+
473
+ ### .not_equal_to(expected_value)
474
+
475
+ Expects a value not to be equal to the expected_value.
476
+
477
+ ```ruby
478
+ expect(...) .not_equal_to(42)
479
+ ```
480
+
481
+ ### .to_match(pattern)
482
+
483
+ Expects a value to match the regular expression pattern.
484
+
485
+ ```ruby
486
+ expect(...) .to_match(/[\d]+^/)
487
+ ```
488
+
489
+ ### .not_to_match(pattern)
490
+
491
+ Expects a value not to match the regular expression pattern.
492
+
493
+ ```ruby
494
+ expect(...) .not_to_match(/[\d]+^/)
495
+ ```
496
+
497
+ ### .to_be_string_as_integer
498
+
499
+ Expects a value to be an integer string.
500
+
501
+ ```ruby
502
+ expect(...) .to_be_string_as_integer
503
+ ```
504
+
505
+ ### .to_be_string_as_double
506
+
507
+ Expects a value to be a double string.
508
+
509
+ ```ruby
510
+ expect(...) .to_be_string_as_double
511
+ ```
512
+
513
+ ### .to_be_in
514
+
515
+ Expects a value to be equal to any value of an array of values.
516
+
517
+ ```ruby
518
+ expect(...) .to_be_in([1, 2, 3])
519
+ ```
520
+
521
+ ### .not_in
522
+
523
+ Expects a value to be different to all the values of an array of values.
524
+
525
+ ```ruby
526
+ expect(...) .not_in([1, 2, 3])
527
+ ```
528
+
529
+ ### .to_be_email
530
+
531
+ Expects a value to be a valid email string.
532
+
533
+ ```ruby
534
+ expect(...) .to_be_email
535
+ ```
536
+
537
+ ### .to_be_url
538
+
539
+ Expects a value to be a valid url string.
540
+
541
+ ```ruby
542
+ expect(...) .to_be_url
543
+ ```
544
+
545
+ ### .to_be_in_range
546
+
547
+ Expects a value to be in a range.
548
+
549
+ ```ruby
550
+ expect(...) .to_be_in_range( CabezaDeTermo::JsonSpec::Range.newFrom('(', 0, 10, ']') )
551
+ ```
552
+
553
+ ### .not_in_range
554
+
555
+ Expects a value not to be in a range.
556
+
557
+ ```ruby
558
+ expect(...) .not_in_range( CabezaDeTermo::JsonSpec::Range.newFrom('(', 0, 10, ']') )
559
+ ```
560
+
561
+ ### .to_be_between
562
+
563
+ Expects a value to be between 2 values, including them.
564
+
565
+ ```ruby
566
+ expect(...) .to_be_between(0, 10)
567
+ ```
568
+
569
+ ### .not_between
570
+
571
+ Expects a value not to be between 2 values, including them.
572
+
573
+ ```ruby
574
+ expect(...) .not_between(0, 10)
575
+ ```
576
+
577
+ ### .can_be_absent
578
+
579
+ Allow a field to be absent without failing the expectation.
580
+
581
+ If the field is absent, stop running other expectations for that field.
582
+
583
+ If present, run the rest of the expectations on that value.
584
+
585
+ ```ruby
586
+ expect(...) .can_be_absent .to_be_equal_to(42)
587
+ ```
588
+
589
+ ### .can_be_null
590
+
591
+ Allow a value to be null without failing the expectation.
592
+
593
+ If the value is null, stop running other expectations for that value.
594
+
595
+ If present, run the rest of the expectations on that value.
596
+
597
+ ```ruby
598
+ expect(...) .can_be_null .to_be_equal_to(42)
599
+ ```
600
+
601
+ ### .can_be_undefined
602
+
603
+ Allow a field to be absent or its value to be null without failing the expectation.
604
+
605
+ If the field is absent or its value is null, stop running other expectations for that value.
606
+
607
+ If the field is present and its value is not null, run the rest of the expectations on that value.
608
+
609
+ ```ruby
610
+ expect(...) .can_be_undefined .to_be_equal_to(42)
611
+ ```