restspec 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.
Files changed (202) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +21 -0
  3. data/.gitignore +23 -0
  4. data/.rspec +4 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +6 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +188 -0
  9. data/ROADMAP.md +11 -0
  10. data/Rakefile +20 -0
  11. data/bin/restspec +54 -0
  12. data/bin/templates/Gemfile +3 -0
  13. data/bin/templates/custom_macros.rb +3 -0
  14. data/bin/templates/restspec_config.rb +10 -0
  15. data/bin/templates/spec_helper.rb +19 -0
  16. data/docs/endpoints.md +200 -0
  17. data/docs/helpers.md +40 -0
  18. data/docs/macros.md +140 -0
  19. data/docs/matchers.md +38 -0
  20. data/docs/schemas.md +28 -0
  21. data/docs/tutorial.md +477 -0
  22. data/docs/types.md +134 -0
  23. data/examples/store-api-tests/.rspec +3 -0
  24. data/examples/store-api-tests/Gemfile +4 -0
  25. data/examples/store-api-tests/Gemfile.lock +70 -0
  26. data/examples/store-api-tests/spec/api/category_spec.rb +23 -0
  27. data/examples/store-api-tests/spec/api/product_spec.rb +55 -0
  28. data/examples/store-api-tests/spec/api/restspec/endpoints.rb +39 -0
  29. data/examples/store-api-tests/spec/api/restspec/requirements.rb +0 -0
  30. data/examples/store-api-tests/spec/api/restspec/restspec_config.rb +6 -0
  31. data/examples/store-api-tests/spec/api/restspec/schemas.rb +11 -0
  32. data/examples/store-api-tests/spec/spec_helper.rb +19 -0
  33. data/examples/store-api-tests/spec/support/custom_macros.rb +3 -0
  34. data/examples/store-api-tests/spec/support/custom_matchers.rb +0 -0
  35. data/examples/store-api/.editorconfig +24 -0
  36. data/examples/store-api/.rbenv-vars.example +3 -0
  37. data/examples/store-api/.rspec +4 -0
  38. data/examples/store-api/.ruby-version +1 -0
  39. data/examples/store-api/Gemfile +58 -0
  40. data/examples/store-api/Gemfile.lock +216 -0
  41. data/examples/store-api/Guardfile +39 -0
  42. data/examples/store-api/README.md +1 -0
  43. data/examples/store-api/Rakefile +6 -0
  44. data/examples/store-api/app/assets/images/.keep +0 -0
  45. data/examples/store-api/app/assets/javascripts/application.js +16 -0
  46. data/examples/store-api/app/assets/javascripts/categories.js.coffee +3 -0
  47. data/examples/store-api/app/assets/javascripts/products.js.coffee +3 -0
  48. data/examples/store-api/app/assets/stylesheets/application.css +15 -0
  49. data/examples/store-api/app/assets/stylesheets/categories.css.scss +3 -0
  50. data/examples/store-api/app/assets/stylesheets/products.css.scss +3 -0
  51. data/examples/store-api/app/assets/stylesheets/scaffolds.css.scss +69 -0
  52. data/examples/store-api/app/controllers/application_controller.rb +5 -0
  53. data/examples/store-api/app/controllers/categories_controller.rb +74 -0
  54. data/examples/store-api/app/controllers/concerns/.keep +0 -0
  55. data/examples/store-api/app/controllers/products_controller.rb +74 -0
  56. data/examples/store-api/app/helpers/application_helper.rb +2 -0
  57. data/examples/store-api/app/helpers/categories_helper.rb +2 -0
  58. data/examples/store-api/app/helpers/products_helper.rb +2 -0
  59. data/examples/store-api/app/mailers/.keep +0 -0
  60. data/examples/store-api/app/models/.keep +0 -0
  61. data/examples/store-api/app/models/category.rb +2 -0
  62. data/examples/store-api/app/models/concerns/.keep +0 -0
  63. data/examples/store-api/app/models/product.rb +3 -0
  64. data/examples/store-api/app/views/categories/_form.html.erb +21 -0
  65. data/examples/store-api/app/views/categories/edit.html.erb +6 -0
  66. data/examples/store-api/app/views/categories/index.html.erb +25 -0
  67. data/examples/store-api/app/views/categories/index.json.jbuilder +4 -0
  68. data/examples/store-api/app/views/categories/new.html.erb +5 -0
  69. data/examples/store-api/app/views/categories/show.html.erb +9 -0
  70. data/examples/store-api/app/views/categories/show.json.jbuilder +1 -0
  71. data/examples/store-api/app/views/layouts/application.html.erb +14 -0
  72. data/examples/store-api/app/views/products/_form.html.erb +29 -0
  73. data/examples/store-api/app/views/products/edit.html.erb +6 -0
  74. data/examples/store-api/app/views/products/index.html.erb +29 -0
  75. data/examples/store-api/app/views/products/index.json.jbuilder +4 -0
  76. data/examples/store-api/app/views/products/new.html.erb +5 -0
  77. data/examples/store-api/app/views/products/show.html.erb +19 -0
  78. data/examples/store-api/app/views/products/show.json.jbuilder +6 -0
  79. data/examples/store-api/bin/bundle +3 -0
  80. data/examples/store-api/bin/guard +16 -0
  81. data/examples/store-api/bin/rails +8 -0
  82. data/examples/store-api/bin/rake +8 -0
  83. data/examples/store-api/bin/spring +18 -0
  84. data/examples/store-api/config.ru +4 -0
  85. data/examples/store-api/config/application.rb +30 -0
  86. data/examples/store-api/config/boot.rb +4 -0
  87. data/examples/store-api/config/database.yml +25 -0
  88. data/examples/store-api/config/environment.rb +5 -0
  89. data/examples/store-api/config/environments/development.rb +37 -0
  90. data/examples/store-api/config/environments/production.rb +78 -0
  91. data/examples/store-api/config/environments/test.rb +39 -0
  92. data/examples/store-api/config/initializers/assets.rb +8 -0
  93. data/examples/store-api/config/initializers/backtrace_silencers.rb +7 -0
  94. data/examples/store-api/config/initializers/cookies_serializer.rb +3 -0
  95. data/examples/store-api/config/initializers/filter_parameter_logging.rb +4 -0
  96. data/examples/store-api/config/initializers/inflections.rb +16 -0
  97. data/examples/store-api/config/initializers/mime_types.rb +4 -0
  98. data/examples/store-api/config/initializers/session_store.rb +3 -0
  99. data/examples/store-api/config/initializers/wrap_parameters.rb +14 -0
  100. data/examples/store-api/config/locales/en.yml +23 -0
  101. data/examples/store-api/config/routes.rb +59 -0
  102. data/examples/store-api/config/secrets.yml +22 -0
  103. data/examples/store-api/db/migrate/20141205154816_create_products.rb +11 -0
  104. data/examples/store-api/db/migrate/20141205171104_create_categories.rb +9 -0
  105. data/examples/store-api/db/migrate/20141205171140_add_category_id_to_products.rb +5 -0
  106. data/examples/store-api/db/schema.rb +31 -0
  107. data/examples/store-api/db/seeds.rb +7 -0
  108. data/examples/store-api/lib/assets/.keep +0 -0
  109. data/examples/store-api/lib/tasks/.keep +0 -0
  110. data/examples/store-api/log/.keep +0 -0
  111. data/examples/store-api/public/404.html +67 -0
  112. data/examples/store-api/public/422.html +67 -0
  113. data/examples/store-api/public/500.html +66 -0
  114. data/examples/store-api/public/favicon.ico +0 -0
  115. data/examples/store-api/public/robots.txt +5 -0
  116. data/examples/store-api/spec/controllers/categories_controller_spec.rb +159 -0
  117. data/examples/store-api/spec/controllers/products_controller_spec.rb +159 -0
  118. data/examples/store-api/spec/factories/categories.rb +6 -0
  119. data/examples/store-api/spec/factories/products.rb +8 -0
  120. data/examples/store-api/spec/helpers/categories_helper_spec.rb +15 -0
  121. data/examples/store-api/spec/helpers/products_helper_spec.rb +15 -0
  122. data/examples/store-api/spec/models/category_spec.rb +5 -0
  123. data/examples/store-api/spec/models/product_spec.rb +5 -0
  124. data/examples/store-api/spec/rails_helper.rb +50 -0
  125. data/examples/store-api/spec/requests/categories_spec.rb +10 -0
  126. data/examples/store-api/spec/requests/products_spec.rb +10 -0
  127. data/examples/store-api/spec/routing/categories_routing_spec.rb +35 -0
  128. data/examples/store-api/spec/routing/products_routing_spec.rb +35 -0
  129. data/examples/store-api/spec/spec_helper.rb +85 -0
  130. data/examples/store-api/spec/views/categories/edit.html.erb_spec.rb +18 -0
  131. data/examples/store-api/spec/views/categories/index.html.erb_spec.rb +19 -0
  132. data/examples/store-api/spec/views/categories/new.html.erb_spec.rb +18 -0
  133. data/examples/store-api/spec/views/categories/show.html.erb_spec.rb +14 -0
  134. data/examples/store-api/spec/views/products/edit.html.erb_spec.rb +24 -0
  135. data/examples/store-api/spec/views/products/index.html.erb_spec.rb +25 -0
  136. data/examples/store-api/spec/views/products/new.html.erb_spec.rb +24 -0
  137. data/examples/store-api/spec/views/products/show.html.erb_spec.rb +18 -0
  138. data/examples/store-api/vendor/assets/javascripts/.keep +0 -0
  139. data/examples/store-api/vendor/assets/stylesheets/.keep +0 -0
  140. data/lib/restspec.rb +38 -0
  141. data/lib/restspec/configuration.rb +43 -0
  142. data/lib/restspec/endpoints/dsl.rb +142 -0
  143. data/lib/restspec/endpoints/endpoint.rb +135 -0
  144. data/lib/restspec/endpoints/namespace.rb +89 -0
  145. data/lib/restspec/endpoints/network.rb +39 -0
  146. data/lib/restspec/endpoints/request.rb +11 -0
  147. data/lib/restspec/endpoints/response.rb +53 -0
  148. data/lib/restspec/requirements/dsl.rb +10 -0
  149. data/lib/restspec/requirements/requirement.rb +59 -0
  150. data/lib/restspec/rspec/api_helpers.rb +64 -0
  151. data/lib/restspec/rspec/api_macros.rb +126 -0
  152. data/lib/restspec/rspec/extras.rb +2 -0
  153. data/lib/restspec/rspec/matchers/api_matchers.rb +6 -0
  154. data/lib/restspec/rspec/matchers/be_like_schema.rb +18 -0
  155. data/lib/restspec/rspec/matchers/be_like_schema_array.rb +18 -0
  156. data/lib/restspec/rspec/matchers/have_header.rb +47 -0
  157. data/lib/restspec/rspec/matchers/have_status.rb +17 -0
  158. data/lib/restspec/rspec/matchers/include_where.rb +14 -0
  159. data/lib/restspec/rspec/shared_examples.rb +12 -0
  160. data/lib/restspec/schema/attribute.rb +31 -0
  161. data/lib/restspec/schema/attribute_example.rb +21 -0
  162. data/lib/restspec/schema/checker.rb +73 -0
  163. data/lib/restspec/schema/dsl.rb +36 -0
  164. data/lib/restspec/schema/schema.rb +21 -0
  165. data/lib/restspec/schema/schema_example.rb +28 -0
  166. data/lib/restspec/schema/types.rb +35 -0
  167. data/lib/restspec/schema/types/array_type.rb +34 -0
  168. data/lib/restspec/schema/types/basic_type.rb +35 -0
  169. data/lib/restspec/schema/types/boolean_type.rb +11 -0
  170. data/lib/restspec/schema/types/decimal_string_type.rb +32 -0
  171. data/lib/restspec/schema/types/decimal_type.rb +14 -0
  172. data/lib/restspec/schema/types/embedded_schema_type.rb +28 -0
  173. data/lib/restspec/schema/types/hash_type.rb +25 -0
  174. data/lib/restspec/schema/types/integer_type.rb +11 -0
  175. data/lib/restspec/schema/types/null_type.rb +11 -0
  176. data/lib/restspec/schema/types/one_of_type.rb +21 -0
  177. data/lib/restspec/schema/types/schema_id_type.rb +88 -0
  178. data/lib/restspec/schema/types/string_type.rb +11 -0
  179. data/lib/restspec/shortcuts.rb +8 -0
  180. data/lib/restspec/stores/endpoint_store.rb +25 -0
  181. data/lib/restspec/stores/namespace_store.rb +20 -0
  182. data/lib/restspec/stores/schema_store.rb +19 -0
  183. data/lib/restspec/values/status_code.rb +13 -0
  184. data/lib/restspec/values/super_hash.rb +12 -0
  185. data/lib/restspec/version.rb +3 -0
  186. data/restspec.gemspec +37 -0
  187. data/spec/restspec/endpoints/dsl_spec.rb +269 -0
  188. data/spec/restspec/endpoints/endpoint_spec.rb +146 -0
  189. data/spec/restspec/endpoints/namespace_spec.rb +143 -0
  190. data/spec/restspec/endpoints/response_spec.rb +49 -0
  191. data/spec/restspec/schema/attribute_example_spec.rb +35 -0
  192. data/spec/restspec/schema/dsl_spec.rb +78 -0
  193. data/spec/restspec/schema/schema_example_spec.rb +40 -0
  194. data/spec/restspec/schema/schema_spec.rb +11 -0
  195. data/spec/restspec/schema/types/array_type_spec.rb +56 -0
  196. data/spec/restspec/schema/types/basic_type_spec.rb +62 -0
  197. data/spec/restspec/schema/types/boolean_type_spec.rb +26 -0
  198. data/spec/restspec/schema/types/null_type_spec.rb +25 -0
  199. data/spec/restspec/schema/types/string_type_spec.rb +26 -0
  200. data/spec/restspec/values/status_code_spec.rb +13 -0
  201. data/spec/spec_helper.rb +23 -0
  202. metadata +484 -0
@@ -0,0 +1,17 @@
1
+ require 'rack'
2
+
3
+ RSpec::Matchers.define :have_status do |status_code|
4
+ match do |response|
5
+ response.code == Restspec::Values::StatusCode.new(status_code).value
6
+ end
7
+
8
+ failure_message do |response|
9
+ status_code = Restspec::Values::StatusCode.new(expected).value
10
+ "expected #{response} to have status code: #{status_code} but it was #{response.code}"
11
+ end
12
+
13
+ failure_message_when_negated do |actual|
14
+ status_code = Restspec::Values::StatusCode.new(expected).value
15
+ "expected #{response} to don't have status code: #{status_code} but it was #{response.code}"
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ RSpec::Matchers.define :include_where do |condition|
2
+ match do |array|
3
+ raise "You can use :include_where with an array response" unless array.is_a?(Array)
4
+ array.any? { |item| condition.call(item) }
5
+ end
6
+
7
+ failure_message do |array|
8
+ "expected array to include something according to the block #{condition}"
9
+ end
10
+
11
+ failure_message_when_negated do |actual|
12
+ "expected array to not include something according to the block #{condition}"
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ RSpec.shared_examples :successful_schema_fetch do
2
+ it { should have_status(:ok) }
3
+ it { should be_like_schema }
4
+ end
5
+
6
+ RSpec.shared_examples :a_not_found_test do
7
+ test 'with a unexisting id' do
8
+ url_params(id: 0)
9
+
10
+ it { should have_status(:not_found) }
11
+ end
12
+ end
@@ -0,0 +1,31 @@
1
+ module Restspec
2
+ module Schema
3
+ class Attribute
4
+ attr_reader :name, :type
5
+
6
+ def initialize(name, type, options = {})
7
+ self.name = name
8
+ self.type = type
9
+ self.example_override = options.fetch(:example, nil)
10
+ self.allowed_abilities = options.fetch(:for, [:checks, :examples])
11
+ end
12
+
13
+ def example
14
+ @example ||= example_override
15
+ end
16
+
17
+ def can_generate_examples?
18
+ allowed_abilities.include?(:examples)
19
+ end
20
+
21
+ def can_be_checked?
22
+ allowed_abilities.include?(:checks)
23
+ end
24
+
25
+ private
26
+
27
+ attr_writer :name, :type
28
+ attr_accessor :example_override, :allowed_abilities
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ require 'faker'
2
+
3
+ module Restspec
4
+ module Schema
5
+ class AttributeExample < Struct.new(:attribute)
6
+ def value
7
+ if attribute.example.present?
8
+ attribute.example.try(:call) || attribute.example
9
+ else
10
+ type.example_for(attribute)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def type
17
+ attribute.type
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,73 @@
1
+ module Restspec
2
+ module Schema
3
+ class Checker < Struct.new(:schema)
4
+ def check_array!(array)
5
+ array.each { |item| check!(item) }
6
+ end
7
+
8
+ def check!(object)
9
+ raise NoObjectError.new(object) unless object.is_a?(Hash)
10
+
11
+ schema.attributes.each do |_, attribute|
12
+ if attribute.can_be_checked?
13
+ checker = ObjectChecker.new(object, attribute)
14
+
15
+ raise NoAttributeError.new(object, attribute) if checker.missed_key?
16
+ raise DifferentTypeError.new(object, attribute) if checker.wrong_type?
17
+ end
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ class ObjectChecker < Struct.new(:object, :attribute)
24
+ def missed_key?
25
+ !object.has_key?(attribute.name)
26
+ end
27
+
28
+ def wrong_type?
29
+ !attribute.type.totally_valid?(attribute, object.fetch(attribute.name))
30
+ end
31
+ end
32
+
33
+ class NoAttributeError < StandardError
34
+ attr_accessor :object, :attribute
35
+
36
+ def initialize(object, attribute)
37
+ self.object = object
38
+ self.attribute = attribute
39
+ end
40
+
41
+ def to_s
42
+ "The object #{object} does not have the attribute #{attribute.name}"
43
+ end
44
+ end
45
+
46
+ class DifferentTypeError < StandardError
47
+ attr_accessor :object, :attribute, :value
48
+
49
+ def initialize(object, attribute)
50
+ self.object = object
51
+ self.attribute = attribute
52
+ self.value = object.fetch(attribute.name)
53
+ end
54
+
55
+ def to_s
56
+ "The property #{attribute.name} of #{object} should be of type #{attribute.type} but it was of type #{value.class}"
57
+ end
58
+ end
59
+
60
+ class NoObjectError < StandardError
61
+ attr_accessor :object
62
+
63
+ def initialize(object)
64
+ self.object = object
65
+ end
66
+
67
+ def to_s
68
+ "The object #{object}:#{object.class} is not a hash. It doesn't have attributes to be checked"
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,36 @@
1
+ module Restspec
2
+ module Schema
3
+ class DSL
4
+ attr_reader :schemas
5
+
6
+ def schema(name, &definition)
7
+ dsl = SingleSchemaDSL.new(name)
8
+ dsl.instance_eval(&definition)
9
+ Restspec::SchemaStore.store(dsl.schema)
10
+ end
11
+ end
12
+
13
+ class SingleSchemaDSL
14
+ attr_reader :schema
15
+
16
+ def initialize(name)
17
+ self.schema = Schema.new(name)
18
+ end
19
+
20
+ def attribute(name, type, options = {})
21
+ new_attribute = Attribute.new(name, type, options)
22
+ schema.attributes[name.to_s] = new_attribute
23
+ end
24
+
25
+ Types::ALL.each do |type_name, type_class|
26
+ define_method(type_name) do |options = {}|
27
+ type_class.new(options)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ attr_writer :schema
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,21 @@
1
+ module Restspec
2
+ module Schema
3
+ class Schema
4
+ attr_reader :name, :attributes
5
+
6
+ def initialize(name)
7
+ self.name = name
8
+ self.attributes = {}
9
+ end
10
+
11
+ def extend_with(without: [])
12
+ without.each { |attribute_name| attributes.delete(attribute_name.to_s) }
13
+ self
14
+ end
15
+
16
+ private
17
+
18
+ attr_writer :name, :attributes
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ module Restspec
2
+ module Schema
3
+ class SchemaExample
4
+ attr_accessor :schema, :extensions
5
+
6
+ def initialize(schema, extensions = {})
7
+ self.schema = schema
8
+ self.extensions = extensions
9
+ end
10
+
11
+ def value
12
+ attributes.inject({}) do |sample, (_, attribute)|
13
+ if attribute.can_generate_examples?
14
+ sample.merge(attribute.name => AttributeExample.new(attribute).value)
15
+ else
16
+ sample
17
+ end
18
+ end.merge(extensions)
19
+ end
20
+
21
+ private
22
+
23
+ def attributes
24
+ schema.attributes
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,35 @@
1
+ module Restspec
2
+ module Schema
3
+ module Types
4
+ end
5
+ end
6
+ end
7
+
8
+ require_relative './types/basic_type'
9
+ require_relative './types/string_type'
10
+ require_relative './types/integer_type'
11
+ require_relative './types/decimal_type'
12
+ require_relative './types/boolean_type'
13
+ require_relative './types/decimal_string_type'
14
+ require_relative './types/schema_id_type'
15
+ require_relative './types/array_type'
16
+ require_relative './types/one_of_type'
17
+ require_relative './types/hash_type'
18
+ require_relative './types/null_type'
19
+ require_relative './types/embedded_schema_type'
20
+
21
+ module Restspec::Schema::Types
22
+ ALL = {
23
+ string: StringType,
24
+ integer: IntegerType,
25
+ decimal: DecimalType,
26
+ boolean: BooleanType,
27
+ decimal_string: DecimalStringType,
28
+ schema_id: SchemaIdType,
29
+ array: ArrayType,
30
+ one_of: OneOfType,
31
+ hash: HashType,
32
+ null: NullType,
33
+ embedded_schema: EmbeddedSchemaType
34
+ }
35
+ end
@@ -0,0 +1,34 @@
1
+ module Restspec::Schema::Types
2
+ class ArrayType < BasicType
3
+ def example_for(attribute)
4
+ length_only_works_with_parameterized_types!
5
+
6
+ example_length.times.map do
7
+ parameterized_type.example_for(attribute)
8
+ end
9
+ end
10
+
11
+ def valid?(attribute, value)
12
+ is_array = value.is_a?(Array)
13
+ if parameterized_type
14
+ is_array && value.all? do |item|
15
+ parameterized_type.totally_valid?(attribute, item)
16
+ end
17
+ else
18
+ is_array
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def example_length
25
+ example_options.fetch(:length, 0)
26
+ end
27
+
28
+ def length_only_works_with_parameterized_types!
29
+ if example_options.has_key?(:length) && !parameterized_type
30
+ raise "To use the :length option you need to have a parameterized_type or we can't generate the array"
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,35 @@
1
+ class Restspec::Schema::Types::BasicType
2
+ def initialize(options = {})
3
+ self.options = options
4
+ end
5
+
6
+ def |(other_type)
7
+ self.disjuction = other_type
8
+ self
9
+ end
10
+
11
+ def of(other_type)
12
+ self.parameterized_type = other_type
13
+ self
14
+ end
15
+
16
+ def totally_valid?(attribute, value)
17
+ if disjuction.present?
18
+ valid?(attribute, value) || disjuction.valid?(attribute, value)
19
+ else
20
+ valid?(attribute, value)
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ attr_accessor :options, :disjuction, :parameterized_type
27
+
28
+ def example_options
29
+ options.fetch(:example_options, options)
30
+ end
31
+
32
+ def schema_options
33
+ options.fetch(:schema_options, options)
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ module Restspec::Schema::Types
2
+ class BooleanType < BasicType
3
+ def example_for(attribute)
4
+ [true, false].sample
5
+ end
6
+
7
+ def valid?(attribute, value)
8
+ [true, false].include?(value)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,32 @@
1
+ module Restspec::Schema::Types
2
+ class DecimalStringType < DecimalType
3
+ def example_for(attribute)
4
+ super(attribute).to_s
5
+ end
6
+
7
+ def valid?(attribute, value)
8
+ return false unless value.is_a?(String)
9
+ decimal_regex.match(value).present?
10
+ end
11
+
12
+ private
13
+
14
+ def decimal_regex
15
+ @decimal_regex ||= build_regex
16
+ end
17
+
18
+ def build_regex
19
+ integer_part_limit = to_regexp_limit(schema_options.fetch(:integer_part, nil))
20
+ decimal_part_limit = to_regexp_limit(schema_options.fetch(:decimal_part, nil))
21
+ /^\d#{integer_part_limit}([.,]\d#{decimal_part_limit})?$/
22
+ end
23
+
24
+ def to_regexp_limit(limit, default = '+')
25
+ if limit.nil?
26
+ default
27
+ else
28
+ "{#{limit}}"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,14 @@
1
+ module Restspec::Schema::Types
2
+ class DecimalType < BasicType
3
+ def example_for(attribute)
4
+ integer_part = example_options.fetch(:integer_part, 2)
5
+ decimal_part = example_options.fetch(:decimal_part, 2)
6
+
7
+ Faker::Number.decimal(integer_part, decimal_part)
8
+ end
9
+
10
+ def valid?(attribute, value)
11
+ value.is_a?(Numeric)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,28 @@
1
+ module Restspec::Schema::Types
2
+ class EmbeddedSchemaType < BasicType
3
+ attr_accessor :schema_name
4
+
5
+ def initialize(options, options_when_name_is_present = {})
6
+ if options.is_a?(Symbol)
7
+ self.schema_name = options
8
+ super(options_when_name_is_present)
9
+ else
10
+ super(options)
11
+ end
12
+ end
13
+
14
+ def example_for(attribute)
15
+ Restspec::Schema::SchemaExample.new(schema).value
16
+ end
17
+
18
+ def valid?(attribute, value)
19
+ Restspec::Schema::Checker.new(schema).check!(value)
20
+ end
21
+
22
+ private
23
+
24
+ def schema
25
+ @schema ||= Restspec::SchemaStore.get(schema_name)
26
+ end
27
+ end
28
+ end