restspec 0.0.4 → 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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +5 -0
  3. data/CHANGELOG.md +0 -0
  4. data/README.md +11 -7
  5. data/Rakefile +7 -0
  6. data/bin/restspec +1 -1
  7. data/examples/store-api-tests/Gemfile.lock +3 -1
  8. data/examples/store-api-tests/api.md +47 -47
  9. data/examples/store-api-tests/spec/api/product_spec.rb +0 -2
  10. data/examples/store-api-tests/spec/api/restspec/endpoints.rb +6 -5
  11. data/examples/store-api-tests/spec/api/restspec/schemas.rb +2 -1
  12. data/{docs → guides}/endpoints.md +0 -0
  13. data/{docs → guides}/helpers.md +0 -0
  14. data/{docs → guides}/macros.md +0 -0
  15. data/{docs → guides}/matchers.md +0 -0
  16. data/{docs → guides}/schemas.md +0 -0
  17. data/{docs → guides}/tutorial.md +1 -1
  18. data/{docs → guides}/types.md +0 -0
  19. data/lib/restspec/configuration.rb +28 -4
  20. data/lib/restspec/endpoints/dsl.rb +281 -48
  21. data/lib/restspec/endpoints/endpoint.rb +18 -58
  22. data/lib/restspec/endpoints/has_schemas.rb +39 -0
  23. data/lib/restspec/endpoints/namespace.rb +4 -7
  24. data/lib/restspec/endpoints/network.rb +27 -0
  25. data/lib/restspec/endpoints/request.rb +3 -0
  26. data/lib/restspec/endpoints/response.rb +3 -0
  27. data/lib/restspec/endpoints/url_builder.rb +51 -0
  28. data/lib/restspec/rspec/api_macros.rb +2 -2
  29. data/lib/restspec/rspec/matchers/be_like_schema.rb +1 -1
  30. data/lib/restspec/rspec/matchers/be_like_schema_array.rb +1 -1
  31. data/lib/restspec/runners/docs/templates/docs.md.erb +2 -2
  32. data/lib/restspec/schema/attribute.rb +43 -0
  33. data/lib/restspec/schema/attribute_example.rb +13 -1
  34. data/lib/restspec/schema/checker.rb +80 -8
  35. data/lib/restspec/schema/dsl.rb +67 -11
  36. data/lib/restspec/schema/schema.rb +13 -1
  37. data/lib/restspec/schema/schema_example.rb +7 -1
  38. data/lib/restspec/schema/types/array_type.rb +42 -1
  39. data/lib/restspec/schema/types/basic_type.rb +62 -0
  40. data/lib/restspec/schema/types/boolean_type.rb +10 -0
  41. data/lib/restspec/schema/types/date_type.rb +12 -0
  42. data/lib/restspec/schema/types/datetime_type.rb +16 -0
  43. data/lib/restspec/schema/types/decimal_string_type.rb +16 -5
  44. data/lib/restspec/schema/types/decimal_type.rb +17 -1
  45. data/lib/restspec/schema/types/embedded_schema_type.rb +39 -8
  46. data/lib/restspec/schema/types/hash_type.rb +51 -12
  47. data/lib/restspec/schema/types/integer_type.rb +12 -1
  48. data/lib/restspec/schema/types/null_type.rb +7 -0
  49. data/lib/restspec/schema/types/one_of_type.rb +18 -0
  50. data/lib/restspec/schema/types/schema_id_type.rb +14 -17
  51. data/lib/restspec/schema/types/string_type.rb +9 -0
  52. data/lib/restspec/schema/types/type_methods.rb +32 -0
  53. data/lib/restspec/schema/types.rb +1 -18
  54. data/lib/restspec/shortcuts.rb +10 -0
  55. data/lib/restspec/stores/endpoint_store.rb +27 -2
  56. data/lib/restspec/stores/namespace_store.rb +23 -4
  57. data/lib/restspec/stores/schema_store.rb +15 -0
  58. data/lib/restspec/values/status_code.rb +16 -1
  59. data/lib/restspec/version.rb +1 -1
  60. data/lib/restspec.rb +2 -0
  61. data/restspec.gemspec +2 -0
  62. data/spec/restspec/endpoints/dsl_spec.rb +32 -19
  63. data/spec/restspec/endpoints/endpoint_spec.rb +20 -43
  64. data/spec/restspec/endpoints/namespace_spec.rb +0 -7
  65. data/spec/restspec/endpoints/request_spec.rb +33 -0
  66. data/spec/restspec/schema/attribute_spec.rb +44 -0
  67. data/spec/restspec/schema/checker_spec.rb +57 -0
  68. data/spec/restspec/schema/dsl_spec.rb +1 -1
  69. data/spec/restspec/schema/schema_spec.rb +15 -0
  70. data/spec/restspec/schema/types/basic_type_spec.rb +2 -2
  71. data/spec/restspec/schema/types/decimal_string_type_spec.rb +56 -0
  72. data/spec/restspec/schema/types/decimal_type_spec.rb +25 -0
  73. data/spec/restspec/schema/types/embedded_schema_type_spec.rb +32 -0
  74. data/spec/restspec/schema/types/hash_type_spec.rb +39 -0
  75. data/spec/restspec/schema/types/integer_type_spec.rb +28 -0
  76. data/spec/restspec/schema/types/one_of_type_spec.rb +21 -0
  77. data/spec/restspec/stores/endpoint_store_spec.rb +62 -0
  78. metadata +63 -10
  79. data/ROADMAP.md +0 -13
@@ -1,9 +1,25 @@
1
1
  module Restspec::Schema::Types
2
+ # Manages DateTime
3
+ #
4
+ # Options:
5
+ # Example:
6
+ # initial_interval: The initial interval (default: 2 months ago)
7
+ # final_interval: The final interval (default: `Time.now`)
2
8
  class DateTimeType < BasicType
9
+ # Generates an example time formatted as ISO8601.
10
+ #
11
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
12
+ # @return [string] A time between 1 month ago and now formatted as ISO8601.
3
13
  def example_for(attribute)
4
14
  Faker::Time.between(initial_example_interval, final_example_interval).iso8601
5
15
  end
6
16
 
17
+ # Validates is the value is a correct time according to ISO8601.
18
+ #
19
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
20
+ # @param value [Object] the value of the attribute.
21
+ #
22
+ # @return [true, false] If the value is accord to ISO8601.
7
23
  def valid?(attribute, value)
8
24
  return false unless value.present?
9
25
  allowed_date_time_formats.any? do |format|
@@ -1,9 +1,20 @@
1
1
  module Restspec::Schema::Types
2
2
  class DecimalStringType < DecimalType
3
+ # Generates a example decimal wrapped in a string. See {DecimalType#example_for}
4
+ # for more details of the example generation.
5
+ #
6
+ # @param (see DecimalType#example_for)
7
+ # @return A random decimal number wrapped in a string.
3
8
  def example_for(attribute)
4
9
  super(attribute).to_s
5
10
  end
6
11
 
12
+ # Checks is a value is a string and it contains a decimal number
13
+ #
14
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
15
+ # @param value [Object] the value of the attribute.
16
+ #
17
+ # @return [true, false] If the value is a string containing a decimal number.
7
18
  def valid?(attribute, value)
8
19
  return false unless value.is_a?(String)
9
20
  decimal_regex.match(value).present?
@@ -12,10 +23,6 @@ module Restspec::Schema::Types
12
23
  private
13
24
 
14
25
  def decimal_regex
15
- @decimal_regex ||= build_regex
16
- end
17
-
18
- def build_regex
19
26
  integer_part_limit = to_regexp_limit(schema_options.fetch(:integer_part, nil))
20
27
  decimal_part_limit = to_regexp_limit(schema_options.fetch(:decimal_part, nil))
21
28
  /^\d#{integer_part_limit}([.,]\d#{decimal_part_limit})?$/
@@ -25,7 +32,11 @@ module Restspec::Schema::Types
25
32
  if limit.nil?
26
33
  default
27
34
  else
28
- "{#{limit}}"
35
+ if limit > 1
36
+ "{1,#{limit}}"
37
+ else
38
+ "{0,#{limit}}"
39
+ end
29
40
  end
30
41
  end
31
42
  end
@@ -1,12 +1,28 @@
1
1
  module Restspec::Schema::Types
2
+ # Represents a decimal number. It has the following options:
3
+ # - example_options:
4
+ # - integer_part: The integer part precision of the generated decimal. (Default: 2)
5
+ # - decimal_part: The decimal part precision of the generated decimal. (Default: 2)
2
6
  class DecimalType < BasicType
7
+ # Generates a random decimal number of 2 digits as integer part
8
+ # and 2 digits as decimal part. Both can be overrided using the
9
+ # example options `integer_part` and `decimal_part`.
10
+ #
11
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
12
+ # @return A random decimal number.
3
13
  def example_for(attribute)
4
14
  integer_part = example_options.fetch(:integer_part, 2)
5
15
  decimal_part = example_options.fetch(:decimal_part, 2)
6
16
 
7
- Faker::Number.decimal(integer_part, decimal_part)
17
+ Faker::Number.decimal(integer_part, decimal_part).to_f
8
18
  end
9
19
 
20
+ # Validates if the number is a numeric one.
21
+ #
22
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
23
+ # @param value [Object] the value of the attribute.
24
+ #
25
+ # @return [true, false] If the value is a number
10
26
  def valid?(attribute, value)
11
27
  value.is_a?(Numeric)
12
28
  end
@@ -1,22 +1,53 @@
1
1
  module Restspec::Schema::Types
2
+ # An embedded schema is an attribute with all
3
+ # the options of a given schema.
2
4
  class EmbeddedSchemaType < BasicType
3
5
  attr_accessor :schema_name
4
6
 
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
7
+ def initialize(schema_name, options = {})
8
+ self.schema_name = schema_name
9
+ super(options)
12
10
  end
13
11
 
12
+ # Generates examples by creating a {SchemaExample} using
13
+ # the passed schema.
14
+ #
15
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema to use.
14
16
  def example_for(attribute)
15
17
  Restspec::Schema::SchemaExample.new(schema).value
16
18
  end
17
19
 
20
+ # Checks if the value is an embedded valid example of the schema
21
+ # used to initialize.
22
+ #
23
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
24
+ # @param value [Object] the value of the attribute.
25
+ #
26
+ # @example
27
+ # # Let's assume this schema
28
+ # schema :category do
29
+ # attribute :name, string
30
+ # end
31
+ #
32
+ # # We can do this anywhere
33
+ # schema :product do
34
+ # attribute :name, string
35
+ # attribute :category, embedded_schema(:category)
36
+ # end
37
+ #
38
+ # { name: 'Something', category: { name: 'Products' } } # a valid product!
39
+ # { name: 'Something' } # an invalid product!
40
+ #
41
+ # @return [true, false] If the value is an embedded valid example of the schema.
18
42
  def valid?(attribute, value)
19
- Restspec::Schema::Checker.new(schema).check!(value)
43
+ begin
44
+ Restspec::Schema::Checker.new(schema).check!(value)
45
+ true
46
+ rescue Restspec::Schema::Checker::NoAttributeError,
47
+ Restspec::Schema::Checker::InvalidationError,
48
+ Restspec::Schema::Checker::NoObjectError
49
+ false
50
+ end
20
51
  end
21
52
 
22
53
  private
@@ -1,24 +1,63 @@
1
1
  module Restspec::Schema::Types
2
+ # It represent embedded hashes, but not schematic ones. For them
3
+ # use the {EmbeddedSchemaType}.
4
+ #
5
+ # This Hash can receive the following options:
6
+ # - schema_options:
7
+ # - value_type: A type specifying the type of the values of the hash.
8
+ # - keys: What are the keys that should be present in the hash.
9
+ #
2
10
  class HashType < BasicType
11
+ # Generates an empty hash for a example.
12
+ # It could be better soon.
13
+ #
14
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
15
+ #
16
+ # @return [Hash] An empty Hash.
3
17
  def example_for(attribute)
4
18
  {}
5
19
  end
6
20
 
21
+ # Checks if the object is a valid hash with the specified keys if they are specified
22
+ # or the specified value type.
23
+ #
24
+ # @example
25
+ # HashType.new.valid?(attribute, { a: 1 })
26
+ # # => true
27
+ # HashType.new(schema_options: { keys: ['age', 'name'] }).valid?(attribute, { a: 1 })
28
+ # # => false
29
+ # HashType.new(schema_options: { keys: ['age', 'name'] }).valid?(attribute, { age: 1, name: 'John' })
30
+ # # => true
31
+ # HashType.new(schema_options: { value_type: StringType.new }).valid?(attribute, { a: 1 })
32
+ # # => false
33
+ # HashType.new(schema_options: { value_type: StringType.new }).valid?(attribute, { a: "1" })
34
+ # # => true
35
+ #
36
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
37
+ # @param value [Object] the value of the attribute.
38
+ #
39
+ # @return [true, false] If the value is a correct Hash.
7
40
  def valid?(attribute, value)
8
- is_hash = value.is_a?(Hash)
9
- keys = schema_options.fetch(:keys, [])
41
+ value.is_a?(Hash) && valid_keys?(value) && valid_value_types?(attribute, value)
42
+ end
43
+
44
+ private
45
+
46
+ def valid_keys?(value)
47
+ keys = schema_options.fetch(:keys, nil)
48
+ return true if keys.nil?
49
+
50
+ keys.all? do |key|
51
+ value.has_key?(key)
52
+ end
53
+ end
10
54
 
11
- if keys.empty?
12
- is_hash
13
- else
14
- value_type = schema_options.fetch(:value_type, nil)
55
+ def valid_value_types?(attribute, value)
56
+ value_type = schema_options.fetch(:value_type, nil)
57
+ return true if value_type.nil?
15
58
 
16
- is_hash && keys.all? do |key|
17
- has_key = value.has_key?(key)
18
- if has_key && value_type
19
- has_key && value_type.totally_valid?(attribute, value[key])
20
- end
21
- end
59
+ value.all? do |key, val|
60
+ value_type.totally_valid?(attribute, val)
22
61
  end
23
62
  end
24
63
  end
@@ -1,9 +1,20 @@
1
1
  module Restspec::Schema::Types
2
2
  class IntegerType < BasicType
3
+ # Generates a random number.
4
+ #
5
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
6
+ #
7
+ # @return [Fixnum] A random number.
3
8
  def example_for(attribute)
4
- Faker::Number.digit
9
+ Faker::Number.digit.to_i
5
10
  end
6
11
 
12
+ # Validates if the value is an integer (Fixnum).
13
+ #
14
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
15
+ # @param value [Object] the value of the attribute.
16
+ #
17
+ # @return [true, false] If the value is an integer.
7
18
  def valid?(attribute, value)
8
19
  value.is_a?(Fixnum)
9
20
  end
@@ -1,9 +1,16 @@
1
1
  module Restspec::Schema::Types
2
2
  class NullType < BasicType
3
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
4
+ #
5
+ # @return nil
3
6
  def example_for(attribute)
4
7
  nil
5
8
  end
6
9
 
10
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
11
+ # @param value [Object] the value of the attribute.
12
+ #
13
+ # @return [true, false] If the value is nil.
7
14
  def valid?(attribute, value)
8
15
  value.nil?
9
16
  end
@@ -1,9 +1,27 @@
1
1
  module Restspec::Schema::Types
2
+ # It will return an element of a set of elements while making a
3
+ # example and checks against that same set of element while
4
+ # validating. The following options are needed:
5
+ #
6
+ # elements: An array of the element to use
7
+ #
8
+ # @example:
9
+ # attribute :pet_type, one_of(elements: %w{dog cat})
10
+ #
2
11
  class OneOfType < BasicType
12
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
13
+ #
14
+ # @return [Object] A sample of the elements array.
15
+ # @raise KeyError if the elements option was not initialized.
3
16
  def example_for(attribute)
4
17
  elements.sample
5
18
  end
6
19
 
20
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
21
+ # @param value [Object] the value of the attribute.
22
+ #
23
+ # @return [true, false] If the value is included in the elements.
24
+ # @raise KeyError if the elements option was not initialized.
7
25
  def valid?(attribute, value)
8
26
  elements.include?(value)
9
27
  end
@@ -1,29 +1,21 @@
1
1
  module Restspec::Schema::Types
2
2
  class SchemaIdType < BasicType
3
- attr_accessor :schema_name
4
3
 
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
4
+ def initialize(schema_name, options = {})
5
+ self.schema_name = schema_name
6
+ super(options)
12
7
  end
13
8
 
14
9
  def example_for(attribute)
15
10
  return sample_item.id if sample_item.present?
16
11
 
17
- if create_response.code == 201 && create_response.body.try(:id)
12
+ if create_response.code == 201 && create_response.body.try(:id).present?
18
13
  create_response.body.id
19
14
  else
20
- example_options.fetch(:hardcoded_fallback) {
21
- raise "We couldn't fetch any information for this example"
22
- }
15
+ hardcoded_fallback
23
16
  end
24
17
  rescue URI::InvalidURIError, Errno::ECONNREFUSED => e
25
- puts "WARNING: Error calling api #{e}. Falling back to use a number."
26
- Faker::Number.digit
18
+ hardcoded_fallback
27
19
  end
28
20
 
29
21
  def valid?(attribute, value)
@@ -33,6 +25,8 @@ module Restspec::Schema::Types
33
25
 
34
26
  private
35
27
 
28
+ attr_accessor :schema_name
29
+
36
30
  def find_endpoint(name)
37
31
  Restspec::EndpointStore.get(name)
38
32
  end
@@ -43,7 +37,7 @@ module Restspec::Schema::Types
43
37
 
44
38
  def get_index_endpoint
45
39
  if schema_name.present?
46
- Restspec::EndpointStore.get_by_schema_and_name(schema_name, :index)
40
+ Restspec::EndpointStore.get_by_schema_name_and_role(schema_name, :index, :response)
47
41
  else
48
42
  find_endpoint(example_options.fetch(:fetch_endpoint))
49
43
  end
@@ -60,8 +54,7 @@ module Restspec::Schema::Types
60
54
 
61
55
  def get_create_endpoint
62
56
  if schema_name.present?
63
- namespace = Restspec::Endpoints::Namespace.get_by_schema_name(schema_name)
64
- namespace.get_endpoint(:create)
57
+ Restspec::EndpointStore.get_by_schema_name_and_role(schema_name, :create, :payload)
65
58
  else
66
59
  find_endpoint(example_options.fetch(:create_endpoint))
67
60
  end
@@ -87,5 +80,9 @@ module Restspec::Schema::Types
87
80
  fetch_endpoint = get_index_endpoint
88
81
  fetch_endpoint.execute.body
89
82
  end
83
+
84
+ def hardcoded_fallback
85
+ example_options.fetch(:hardcoded_fallback, Faker::Number.digit)
86
+ end
90
87
  end
91
88
  end
@@ -1,9 +1,18 @@
1
1
  module Restspec::Schema::Types
2
2
  class StringType < BasicType
3
+ # Generates a random word.
4
+ #
5
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
6
+ #
7
+ # @return [String] A random word.
3
8
  def example_for(attribute)
4
9
  Faker::Lorem.word
5
10
  end
6
11
 
12
+ # @param attribute [Restspec::Schema::Attribute] the atribute of the schema.
13
+ # @param value [Object] the value of the attribute.
14
+ #
15
+ # @return [true, false] If the value is a string.
7
16
  def valid?(attribute, value)
8
17
  value.is_a?(String)
9
18
  end
@@ -0,0 +1,32 @@
1
+ module Restspec::Schema::Types
2
+ module TypeMethods
3
+ # @private
4
+ # @!macro type_method
5
+ # @!method $1(options = {})
6
+ #
7
+ # Creates a new {$2} instance with the first argument
8
+ # passed as parameter to the {$2} constructor.
9
+ #
10
+ # @param options [Hash, Object] A hash of options or
11
+ # something to instantiate the type.
12
+ def self.define_type_method(method_name, type_class)
13
+ define_method(method_name) do |options = {}|
14
+ type_class.new(options)
15
+ end
16
+ end
17
+
18
+ define_type_method :string, StringType
19
+ define_type_method :integer, IntegerType
20
+ define_type_method :decimal, DecimalType
21
+ define_type_method :boolean, BooleanType
22
+ define_type_method :decimal_string, DecimalStringType
23
+ define_type_method :schema_id, SchemaIdType
24
+ define_type_method :array, ArrayType
25
+ define_type_method :one_of, OneOfType
26
+ define_type_method :hash, HashType
27
+ define_type_method :null, NullType
28
+ define_type_method :embedded_schema, EmbeddedSchemaType
29
+ define_type_method :date, DateType
30
+ define_type_method :datetime, DateTimeType
31
+ end
32
+ end
@@ -19,21 +19,4 @@ require_relative './types/null_type'
19
19
  require_relative './types/embedded_schema_type'
20
20
  require_relative './types/date_type'
21
21
  require_relative './types/datetime_type'
22
-
23
- module Restspec::Schema::Types
24
- ALL = {
25
- string: StringType,
26
- integer: IntegerType,
27
- decimal: DecimalType,
28
- boolean: BooleanType,
29
- decimal_string: DecimalStringType,
30
- schema_id: SchemaIdType,
31
- array: ArrayType,
32
- one_of: OneOfType,
33
- hash: HashType,
34
- null: NullType,
35
- embedded_schema: EmbeddedSchemaType,
36
- date: DateType,
37
- datetime: DateTimeType
38
- }
39
- end
22
+ require_relative './types/type_methods'
@@ -1,5 +1,15 @@
1
1
  module Restspec
2
2
  class << self
3
+ # Shortcut for find a schema by name, create a {Restspec::Schema::SchemaExample} and call its {Restspec::Schema::SchemaExample#value value} method to get a example.
4
+ #
5
+ # @param schema_name [Symbol] The name of the schema.
6
+ # @param extensions [Hash] A set of extensions for the example.
7
+ #
8
+ # @example Without extensions
9
+ # Restspec.example_for(:person) # { name: 'John', age: 25 }
10
+ #
11
+ # @example With extensions
12
+ # Restspec.example_for(:person, age: 18) # { name: 'John', age: 18 }
3
13
  def example_for(schema_name, extensions = {})
4
14
  schema = Restspec::SchemaStore.get(schema_name)
5
15
  Schema::SchemaExample.new(schema, extensions).value
@@ -2,24 +2,49 @@ require 'delegate'
2
2
 
3
3
  module Restspec
4
4
  module Stores
5
+ # Provides methods for the {EndpointStore} object.
5
6
  class EndpointStoreDelegator < SimpleDelegator
7
+ # Stores an endpoint. It uses the {Restspec::Endpoints::Endpoint#full_name full_name}
8
+ # method of the endpoint to use as the key for the endpoint itself.
9
+ #
10
+ # @param endpoint [Restspec::Endpoints::Endpoint] the endpoint to store.
11
+ # @return [Restspec::Endpoints::Endpoint] the endpoint inserted.
6
12
  def store(endpoint)
7
13
  self[endpoint.full_name] = endpoint
8
14
  end
9
15
 
16
+ # Get is just an alias for Hash#[]
17
+ # @return [Restspec::Endpoints::Endpoint, nil] the endpoint found.
10
18
  def get(endpoint_name)
11
19
  self[endpoint_name]
12
20
  end
13
21
 
14
- def get_by_schema_and_name(schema_name, endpoint_name)
22
+ # Get an endpoint by the schema, name and a role.
23
+ #
24
+ # @example
25
+ # # Let's assume in the store there are 3 endpoints
26
+ # # called :show, in different namespaces.
27
+ #
28
+ # Restspec::EndpointStore.get_by_schema_name_and_role(:book, :show, :response)
29
+ # # => this will only return the one whose schema is :book and are suitable for response.
30
+ #
31
+ # @return [Restspec::Endpoints::Endpoint, nil] the endpoint found.
32
+ def get_by_schema_name_and_role(schema_name, endpoint_name, role)
15
33
  values.find do |endpoint|
16
- endpoint.schema_name == schema_name && endpoint.name == endpoint_name
34
+ endpoint.name == endpoint_name && endpoint.schema_for(role).try(:name) == schema_name
17
35
  end
18
36
  end
19
37
  end
20
38
 
39
+ # The Endpoint Store is a Hash extended using {Stores::EndpointStoreDelegator}
40
+ # This is where we store the endpoints to tests.
41
+ #
42
+ # It's important to note that, because this is a Hash, there can't be
43
+ # two endpoint with the same full name. There can't be two endpoints
44
+ # called `books/index` for example.
21
45
  EndpointStore = EndpointStoreDelegator.new(Hash.new)
22
46
  end
23
47
 
48
+ # (see Stores::EndpointStore)
24
49
  EndpointStore = Stores::EndpointStore
25
50
  end
@@ -2,19 +2,38 @@ require 'delegate'
2
2
 
3
3
  module Restspec
4
4
  module Stores
5
+ # Provides methods for the {NamespaceStore} object.
5
6
  class NamespaceStoreDelegator < SimpleDelegator
7
+ # Stores the namespace. It uses the namespace's name as the hash key.
8
+ #
9
+ # @param namespace [Restspec::Endpoints::Namespace] the namespace to store.
10
+ # @raise [StandardError] if the namespace is an anonymous one.
6
11
  def store(namespace)
7
- self << namespace
12
+ if namespace.anonymous?
13
+ raise "Can't add an anonymous namespace to the NamespaceStore"
14
+ else
15
+ self[namespace.name] = namespace
16
+ end
8
17
  end
9
18
 
19
+ # Get a namespace by name. It gets the name as string or symbol.
20
+ #
21
+ # @param namespace_name [String, Symbol] the namespace's name to use for search.
22
+ # @return [Restspec::Endpoints::Namespace, nil] the namespace found.
10
23
  def get(namespace_name)
11
- possible_names = [namespace_name.to_s, namespace_name.to_sym]
12
- find { |ns| possible_names.include?(ns.name) }
24
+ fetch(namespace_name.to_s) { fetch(namespace_name.to_sym, nil) }
13
25
  end
14
26
  end
15
27
 
16
- NamespaceStore = NamespaceStoreDelegator.new(Array.new)
28
+ # The Namespace Store is a Hash extended using {Stores::NamespaceStoreDelegator}
29
+ # This is where we store the namespaces of the API.
30
+ #
31
+ # It's important to note that, because this is a Hash, there can't be
32
+ # two namespaces with the same name. Anonymous namespaces can't be stored
33
+ # here. They are just stored as children of each namespace.
34
+ NamespaceStore = NamespaceStoreDelegator.new(Hash.new)
17
35
  end
18
36
 
37
+ # (see Stores::NamespaceStore)
19
38
  NamespaceStore = Stores::NamespaceStore
20
39
  end
@@ -2,18 +2,33 @@ require 'delegate'
2
2
 
3
3
  module Restspec
4
4
  module Stores
5
+ # Provides methods for the {SchemaStore} object.
5
6
  class SchemaStoreDelegator < SimpleDelegator
7
+ # Stores a schema. It uses the name of the schema as the hash key.
8
+ #
9
+ # @param schema [Restspec::Schema::Schema] the schema to store.
10
+ # @return [Restspec::Schema::Schema] the schema inserted.
6
11
  def store(schema)
7
12
  self[schema.name] = schema
8
13
  end
9
14
 
15
+ # Get the schema. It's just an alias for the Hash#[] method
16
+ #
17
+ # @param schema_name the name of the schema.
18
+ # @return [Restspec::Schema::Schema, nil] the schema found.
10
19
  def get(schema_name)
11
20
  self[schema_name]
12
21
  end
13
22
  end
14
23
 
24
+ # The Schema Store is a Hash extended using {Stores::SchemaStoreDelegator}
25
+ # This is where we store the schemas to use.
26
+ #
27
+ # It's important to note that, because this is a Hash, there can't be
28
+ # two schemas with the same name.
15
29
  SchemaStore = SchemaStoreDelegator.new(Hash.new)
16
30
  end
17
31
 
32
+ # (see Stores::SchemaStore)
18
33
  SchemaStore = Stores::SchemaStore
19
34
  end
@@ -1,6 +1,17 @@
1
1
  module Restspec
2
2
  module Values
3
- class StatusCode < Struct.new(:number_or_symbol)
3
+ # A value object that transforms a http status code (201) or
4
+ # a symbol with the status code message (:created) to a simple
5
+ # number (201).
6
+ class StatusCode
7
+ def initialize(number_or_symbol)
8
+ self.number_or_symbol = number_or_symbol
9
+ end
10
+
11
+ # @example
12
+ # StatusCode.new(201).value # 201
13
+ # StatusCode.new(:created).value # 201
14
+ # @return [Fixnum] the status code
4
15
  def value
5
16
  if number_or_symbol.is_a?(Symbol)
6
17
  Rack::Utils::SYMBOL_TO_STATUS_CODE.fetch(number_or_symbol)
@@ -8,6 +19,10 @@ module Restspec
8
19
  number_or_symbol
9
20
  end
10
21
  end
22
+
23
+ private
24
+
25
+ attr_accessor :number_or_symbol
11
26
  end
12
27
  end
13
28
  end
@@ -1,3 +1,3 @@
1
1
  module Restspec
2
- VERSION = "0.0.4"
2
+ VERSION = "0.1"
3
3
  end
data/lib/restspec.rb CHANGED
@@ -27,8 +27,10 @@ require "restspec/endpoints/dsl"
27
27
  require "restspec/endpoints/request"
28
28
  require "restspec/endpoints/response"
29
29
  require "restspec/endpoints/network"
30
+ require "restspec/endpoints/has_schemas"
30
31
  require "restspec/endpoints/endpoint"
31
32
  require "restspec/endpoints/namespace"
33
+ require "restspec/endpoints/url_builder"
32
34
 
33
35
  require "restspec/requirements/dsl"
34
36
  require "restspec/requirements/requirement"
data/restspec.gemspec CHANGED
@@ -24,6 +24,8 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "guard-rspec", "~> 4.3"
25
25
  spec.add_development_dependency "rspec-nc", "~> 0.2"
26
26
  spec.add_development_dependency "simplecov", "~> 0.9.1"
27
+ spec.add_development_dependency "yard", "~> 0.8.7"
28
+ spec.add_development_dependency "redcarpet", "~> 3.2"
27
29
  spec.add_dependency "activesupport", "~> 4.0"
28
30
  spec.add_dependency "faker", "~> 1.4"
29
31
  spec.add_dependency "hashie", "~> 3.3"