restspec 0.0.4 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
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"