json-spec 0.1.0

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.
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,17 @@
1
+ require_relative "expectation-definition"
2
+ require "cabeza-de-termo/json-spec/instantiators/patial-application-instantiator"
3
+
4
+ module CabezaDeTermo
5
+ module JsonSpec
6
+ class ExpectingExpectationDefinition < ExpectationDefinition
7
+ def expect(expectation_method, *args)
8
+ @expectation_instantiator = expectation_instantiator_for(expectation_method)
9
+ @args = args
10
+ end
11
+
12
+ def expectation_instantiator()
13
+ PartialApplicationInstantiator.new(@expectation_instantiator, @args)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ require_relative "expectation-definition"
2
+ require "cabeza-de-termo/json-spec/instantiators/negated-expectation-instantiator"
3
+
4
+ module CabezaDeTermo
5
+ module JsonSpec
6
+ class NegatingExpectationDefinition < ExpectationDefinition
7
+ def negate(expectation_method)
8
+ @expectation_instantiator = expectation_instantiator_for(expectation_method)
9
+ end
10
+
11
+ def expectation_instantiator()
12
+ NegatedExpectationInstantiator.new(@expectation_instantiator)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,35 @@
1
+ require_relative "modifier-builders/modifiers-definition-builder"
2
+ require_relative "expectation-builders/expectations-definition-builder"
3
+
4
+ module CabezaDeTermo
5
+ module JsonSpec
6
+ class ExpectationLibraryDefinitionBuilder
7
+ # Initializing
8
+
9
+ def initialize(expectations_library)
10
+ @expectations_library = expectations_library
11
+ end
12
+
13
+ # Accessing
14
+
15
+ def expectations_library
16
+ @expectations_library
17
+ end
18
+
19
+ def expectations(&block)
20
+ ExpectationsDefinitionBuilder.for(expectations_library, &block)
21
+ self
22
+ end
23
+
24
+ def modifiers(&block)
25
+ ModifiersDefinitionBuilder.for(expectations_library, &block)
26
+ self
27
+ end
28
+
29
+ def default_expectations(&block)
30
+ Bind.evaluation of: block, to: expectations_library.default_expectations
31
+ self
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ require_relative "modifier-definition"
2
+
3
+ module CabezaDeTermo
4
+ module JsonSpec
5
+ class ClassModifierDefinition < ModifierDefinition
6
+ def klass(klass)
7
+ @klass = klass
8
+ end
9
+
10
+ def modifier_instantiator
11
+ @klass
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ require_relative "modifier-definition"
2
+ require "cabeza-de-termo/json-spec/instantiators/modifier-composite-instantiator"
3
+ require "cabeza-de-termo/json-spec/instantiators/patial-application-instantiator"
4
+
5
+ module CabezaDeTermo
6
+ module JsonSpec
7
+ class ComposingModifiersDefinition < ModifierDefinition
8
+ def initialize(expectations_library)
9
+ super(expectations_library)
10
+
11
+ @modifier_instantiators = []
12
+ end
13
+
14
+ def with(modifier_method, *args)
15
+ @modifier_instantiators << PartialApplicationInstantiator.new(modifier_instantiator_for(modifier_method), args)
16
+ self
17
+ end
18
+
19
+ def modifier_instantiator
20
+ ModifierCompositeInstantiator.with_all(@modifier_instantiators)
21
+ end
22
+
23
+ def modifier_instantiator_for(method_name)
24
+ @expectations_library.modifier_instantiator_for(method_name)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ module CabezaDeTermo
2
+ module JsonSpec
3
+ class ModifierDefinition
4
+ def initialize(expectations_library)
5
+ @expectations_library = expectations_library
6
+ end
7
+
8
+ def modifier_instantiator
9
+ raise 'Subclass responsibility'
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,73 @@
1
+ require_relative "class-modifier-definition"
2
+ require_relative "composing-modifiers-definition"
3
+
4
+ module CabezaDeTermo
5
+ module JsonSpec
6
+ class ModifiersDefinitionBuilder
7
+ def self.for(expectations_library, &block)
8
+ new(expectations_library, &block)
9
+ end
10
+
11
+ def initialize(expectations_library, &block)
12
+ @expectations_library = expectations_library
13
+
14
+ Bind.evaluation of: block, to: self
15
+ end
16
+
17
+ # Accessing
18
+
19
+ def expectations_library
20
+ @expectations_library
21
+ end
22
+
23
+ def method_name
24
+ @method_name
25
+ end
26
+
27
+ def definition
28
+ @definition
29
+ end
30
+
31
+ # Building definition
32
+
33
+ def reset_current_definition
34
+ @method_name = nil
35
+ @definition = nil
36
+ end
37
+
38
+ def define(method_name, &block)
39
+ @method_name = method_name.to_sym
40
+
41
+ block.call
42
+
43
+ define_modifier_in_library
44
+ reset_current_definition
45
+ end
46
+
47
+ def with_class(klass)
48
+ @definition = ClassModifierDefinition.new(expectations_library)
49
+ @definition.klass klass
50
+ end
51
+
52
+ def composing(modifier)
53
+ @definition = ComposingModifiersDefinition.new(expectations_library)
54
+ @definition.with modifier
55
+ end
56
+
57
+ def define_modifier_in_library
58
+ expectations_library.define_modifier(method_name, modifier_instantiator)
59
+ end
60
+
61
+ def modifier_instantiator
62
+ definition.modifier_instantiator
63
+ end
64
+
65
+ # Messages delegation
66
+
67
+ # Delegate every method to the current definition builder
68
+ def method_missing(method_name, *args, &block)
69
+ @definition.send(method_name, *args, &block)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,150 @@
1
+ require_relative "initializers/default-library-initializer"
2
+ require_relative "messages/expectation-messages-mapping"
3
+ require_relative "default-expectations/default-expectations-mapping"
4
+
5
+ require_relative "definition-builders/expectation-library-definition-builder"
6
+
7
+ require "cabeza-de-termo/json-spec/errors/expectation-not-found-error"
8
+ require "cabeza-de-termo/json-spec/errors/modifier-not-found-error"
9
+
10
+ module CabezaDeTermo
11
+ module JsonSpec
12
+ class ExpectationsLibrary
13
+ @current = nil
14
+ @default_library_initializer = nil
15
+
16
+ # Instance accessing
17
+
18
+ def self.current()
19
+ @current = new_default if @current.nil?
20
+ @current
21
+ end
22
+
23
+ def self.set_current(expectations_library)
24
+ to_be_replaced = current
25
+ @current = expectations_library
26
+
27
+ to_be_replaced
28
+ end
29
+
30
+ def self.define(&block)
31
+ current.define(&block)
32
+ end
33
+
34
+ def self.reset()
35
+ @current = nil
36
+ end
37
+
38
+ # Initializing
39
+
40
+ def self.default_library_initializer()
41
+ set_default_library_initializer(new_default_library_initializer) if @default_library_initializer.nil?
42
+
43
+ @default_library_initializer
44
+ end
45
+
46
+ def self.set_default_library_initializer(library_initializer)
47
+ to_be_replaced = @default_library_initializer
48
+ @default_library_initializer = library_initializer
49
+
50
+ to_be_replaced
51
+ end
52
+
53
+ def self.new_default_library_initializer()
54
+ DefaultLibraryInitializer.new
55
+ end
56
+
57
+ def self.new_default()
58
+ default_library_initializer.new_library
59
+ end
60
+
61
+ # Instance methods
62
+
63
+ def initialize()
64
+ @expectations = {}
65
+ @modifiers = {}
66
+ @expectation_messages_mapping = new_expectations_messages_mapping
67
+ @default_expectations_mapping = new_default_expectations_mapping
68
+ end
69
+
70
+ # Accessing
71
+
72
+ def default_expectations()
73
+ @default_expectations_mapping
74
+ end
75
+
76
+ # Defining
77
+
78
+ def define(&block)
79
+ Bind.evaluation of: block, to: ExpectationLibraryDefinitionBuilder.new(self)
80
+ end
81
+
82
+ # Expectation messages
83
+
84
+ def has_message_formatter_for?(expectation_method)
85
+ @expectation_messages_mapping.has_message_formatter_for?(expectation_method)
86
+ end
87
+
88
+ def message_formatter_for(expectation_method)
89
+ @expectation_messages_mapping.message_formatter_for(expectation_method)
90
+ end
91
+
92
+ def define_message_formatter_for(expectation_method, message_block)
93
+ @expectation_messages_mapping.define_message_formatter_for(expectation_method, message_block)
94
+
95
+ self
96
+ end
97
+
98
+ # Expectations
99
+
100
+ def define_expectation(expectation_method, expectation_instantiator)
101
+ @expectations[expectation_method.to_sym] = expectation_instantiator
102
+ self
103
+ end
104
+
105
+ def has_expectation_for?(expectation_method)
106
+ @expectations.key?(expectation_method.to_sym)
107
+ end
108
+
109
+ def expectation_instantiator_for(expectation_method)
110
+ return @expectations[expectation_method.to_sym] if has_expectation_for?(expectation_method)
111
+ raise ExpectationNotFoundError.new("The Expectation method '#{expectation_method}' was not found.")
112
+ end
113
+
114
+ def new_expectation_from_message(message)
115
+ expectation_instantiator_for( message.method_name ).new( *message.args )
116
+ end
117
+
118
+ # Modifiers
119
+
120
+ def define_modifier(expectation_method, modifier_instantiator)
121
+ @modifiers[expectation_method.to_sym] = modifier_instantiator
122
+
123
+ self
124
+ end
125
+
126
+ def has_modifier_for?(expectation_method)
127
+ @modifiers.key?(expectation_method.to_sym)
128
+ end
129
+
130
+ def modifier_instantiator_for(method_name)
131
+ return @modifiers[method_name.to_sym] if has_modifier_for?(method_name)
132
+ raise ModifierNotFoundError.new("The modifier method '#{method_name}' was not found.")
133
+ end
134
+
135
+ def new_modifier_from_message(message)
136
+ modifier_instantiator_for(message.method_name).new( *message.args )
137
+ end
138
+
139
+ # Helpers
140
+
141
+ def new_expectations_messages_mapping()
142
+ ExpectationMessagesMapping.new
143
+ end
144
+
145
+ def new_default_expectations_mapping()
146
+ DefaultExpectationsMapping.new
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,265 @@
1
+ require_relative "library-initializer"
2
+
3
+ require "cabeza-de-termo/json-spec/expectations/is-scalar-expectation"
4
+ require "cabeza-de-termo/json-spec/expectations/is-url-expectation"
5
+ require "cabeza-de-termo/json-spec/expectations/is-email-expectation"
6
+
7
+ require "cabeza-de-termo/json-spec/modifiers/can-be-absent-modifier"
8
+ require "cabeza-de-termo/json-spec/modifiers/can-be-null-modifier"
9
+
10
+ module CabezaDeTermo
11
+ module JsonSpec
12
+ class DefaultLibraryInitializer < LibraryInitializer
13
+ def new_library()
14
+ library = ExpectationsLibrary.new
15
+ define_library(library)
16
+ end
17
+
18
+ def define_library(library)
19
+ library.define do
20
+
21
+ # Define expectations
22
+ expectations do
23
+ define :to_exist do
24
+ with_block { |value_holder, expected_value| value_holder.not_missing_value? }
25
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' exists."
26
+ end
27
+
28
+ define :to_be_absent do
29
+ negating :to_exist
30
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is absent."
31
+ end
32
+
33
+ define :to_be_kind_of do
34
+ with_block { |value_holder, expected_class| value_holder.value.kind_of? expected_class }
35
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is a <%= expectation.args[0] %>."
36
+ end
37
+
38
+ define :to_be_true do
39
+ expecting :to_be_kind_of, ::TrueClass
40
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is true."
41
+ end
42
+
43
+ define :to_be_false do
44
+ expecting :to_be_kind_of, ::FalseClass
45
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is false."
46
+ end
47
+
48
+ define :to_be_boolean do
49
+ expecting_any_of :to_be_true
50
+ or_also :to_be_true
51
+
52
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is a boolean."
53
+ end
54
+
55
+ define :to_be_float do
56
+ expecting :to_be_kind_of, ::Float
57
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is a float."
58
+ end
59
+
60
+ define :to_be_integer do
61
+ expecting :to_be_kind_of, ::Integer
62
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is an integer."
63
+ end
64
+
65
+ define :to_be_list do
66
+ expecting :to_be_kind_of, ::Array
67
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is a list."
68
+ end
69
+
70
+ define :to_be_number do
71
+ expecting :to_be_kind_of, ::Numeric
72
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is a number."
73
+ end
74
+
75
+ define :to_be_scalar do
76
+ with_class IsScalarExpectation
77
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is a scalar."
78
+ end
79
+
80
+ define :to_be_object do
81
+ expecting :to_be_kind_of, ::Hash
82
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is an object."
83
+ end
84
+
85
+ define :to_be_string do
86
+ expecting :to_be_kind_of, ::String
87
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is a string."
88
+ end
89
+
90
+ define :to_be_null do
91
+ with_block { |value_holder, expected_value| value_holder.value.nil? }
92
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is null."
93
+ end
94
+
95
+ define :not_null do
96
+ negating :to_be_null
97
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is not null."
98
+ end
99
+
100
+ define :to_be_defined do
101
+ expecting_all_of :to_exist
102
+ and_also :not_null
103
+
104
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is defined."
105
+ end
106
+
107
+ define :not_defined do
108
+ negating :to_be_defined
109
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is not defined."
110
+ end
111
+
112
+ define :to_be_empty do
113
+ with_block { |value_holder, expected_value| value_holder.is_empty? }
114
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is empty."
115
+ end
116
+
117
+ define :not_empty do
118
+ negating :to_be_empty
119
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is not empty."
120
+ end
121
+
122
+ define :_to_be_blank do
123
+ with_block { |value_holder, expected_value| value_holder.value.strip.empty? }
124
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is blank."
125
+ end
126
+
127
+ define :to_be_blank do
128
+ expecting_all_of :to_be_string
129
+ and_also :_to_be_blank
130
+
131
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is blank."
132
+ end
133
+
134
+ define :not_blank do
135
+ negating :to_be_blank
136
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is not blank."
137
+ end
138
+
139
+ define :to_be_equal_to do
140
+ with_block { |value_holder, expected_value| expected_value == value_holder.value }
141
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is equal to '<%= expectation.args[0] %>'."
142
+ end
143
+
144
+ define :not_equal_to do
145
+ negating :to_be_equal_to
146
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is not equal to '<%= expectation.args[0] %>'."
147
+ end
148
+
149
+ define :_to_match do
150
+ with_block do |value_holder, expected_regex|
151
+ expected_regex.match(value_holder.value) != nil
152
+ end
153
+
154
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' matches '<%= expectation.args[0] %>'."
155
+ end
156
+
157
+ define :to_match do
158
+ expecting_all_of :to_be_string
159
+ and_also :_to_match
160
+
161
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' matches '<%= expectation.child_expectations[1].args[0] %>'."
162
+ end
163
+
164
+ define :not_to_match do
165
+ negating :to_match
166
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' does not match '<%= expectation.child_expectations[1].args[0] %>'."
167
+ end
168
+
169
+ define :to_be_string_as_integer do
170
+ expecting :to_match, /^[-+]?\d+$/
171
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' has a valid integer format."
172
+ end
173
+
174
+ define :to_be_string_as_float do
175
+ expecting :to_match, /^[-+]?[0-9]*\.?[0-9]+$/
176
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' has a valid float format."
177
+ end
178
+
179
+ define :to_be_in do
180
+ with_block do |value_holder, possible_values|
181
+ possible_values.include?( value_holder.value )
182
+ end
183
+
184
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is equal to any of <%= expectation.args[0] %>."
185
+ end
186
+
187
+ define :not_in do
188
+ negating :to_be_in
189
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is not equal to any of <%= expectation.args[0] %>."
190
+ end
191
+
192
+ define :to_be_email do
193
+ with_class IsEmailExpectation
194
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is an email."
195
+ end
196
+
197
+ define :to_be_url do
198
+ with_class IsUrlExpectation
199
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is an url."
200
+ end
201
+
202
+ define :to_be_in_range do
203
+ with_block do |value_holder, expectedRange|
204
+ expectedRange.includes?( value_holder.value )
205
+ end
206
+
207
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is in range <%= expectation.args[0] %>."
208
+ end
209
+
210
+ define :not_in_range do
211
+ negating :to_be_in_range
212
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is not in range <%= expectation.args[0] %>."
213
+ end
214
+
215
+ define :to_be_between do
216
+ with_block do |value_holder, min, max|
217
+ Range::new_from('[', min, max, ']').includes?( value_holder.value )
218
+ end
219
+
220
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is between <%= Range.new(expectation.args[0], expectation.args[1]).to_s %>."
221
+ end
222
+
223
+ define :not_between do
224
+ negating :to_be_between
225
+ message "Failed asserting that the field '<%= field %>' with value = '<%= format value %>' is not between <%= Range.new(expectation.args[0], expectation.args[1]).to_s %>."
226
+ end
227
+ end
228
+
229
+ # Define modifiers
230
+ modifiers do
231
+ define :can_be_absent do
232
+ with_class CanBeAbsentModifier
233
+ end
234
+
235
+ define :can_be_null do
236
+ with_class CanBeNullModifier
237
+ end
238
+
239
+ define :can_be_undefined do
240
+ composing :can_be_null
241
+ with :can_be_absent
242
+ end
243
+ end
244
+
245
+ # Define default expectations
246
+ default_expectations do
247
+ for_every_object do
248
+ to_be_object
249
+ end
250
+
251
+ for_every_list do
252
+ to_be_list
253
+ end
254
+
255
+ for_every_scalar do
256
+ to_be_scalar
257
+ end
258
+ end
259
+ end
260
+
261
+ library
262
+ end
263
+ end
264
+ end
265
+ end