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.
- checksums.yaml +4 -4
- data/.yardopts +5 -0
- data/CHANGELOG.md +0 -0
- data/README.md +11 -7
- data/Rakefile +7 -0
- data/bin/restspec +1 -1
- data/examples/store-api-tests/Gemfile.lock +3 -1
- data/examples/store-api-tests/api.md +47 -47
- data/examples/store-api-tests/spec/api/product_spec.rb +0 -2
- data/examples/store-api-tests/spec/api/restspec/endpoints.rb +6 -5
- data/examples/store-api-tests/spec/api/restspec/schemas.rb +2 -1
- data/{docs → guides}/endpoints.md +0 -0
- data/{docs → guides}/helpers.md +0 -0
- data/{docs → guides}/macros.md +0 -0
- data/{docs → guides}/matchers.md +0 -0
- data/{docs → guides}/schemas.md +0 -0
- data/{docs → guides}/tutorial.md +1 -1
- data/{docs → guides}/types.md +0 -0
- data/lib/restspec/configuration.rb +28 -4
- data/lib/restspec/endpoints/dsl.rb +281 -48
- data/lib/restspec/endpoints/endpoint.rb +18 -58
- data/lib/restspec/endpoints/has_schemas.rb +39 -0
- data/lib/restspec/endpoints/namespace.rb +4 -7
- data/lib/restspec/endpoints/network.rb +27 -0
- data/lib/restspec/endpoints/request.rb +3 -0
- data/lib/restspec/endpoints/response.rb +3 -0
- data/lib/restspec/endpoints/url_builder.rb +51 -0
- data/lib/restspec/rspec/api_macros.rb +2 -2
- data/lib/restspec/rspec/matchers/be_like_schema.rb +1 -1
- data/lib/restspec/rspec/matchers/be_like_schema_array.rb +1 -1
- data/lib/restspec/runners/docs/templates/docs.md.erb +2 -2
- data/lib/restspec/schema/attribute.rb +43 -0
- data/lib/restspec/schema/attribute_example.rb +13 -1
- data/lib/restspec/schema/checker.rb +80 -8
- data/lib/restspec/schema/dsl.rb +67 -11
- data/lib/restspec/schema/schema.rb +13 -1
- data/lib/restspec/schema/schema_example.rb +7 -1
- data/lib/restspec/schema/types/array_type.rb +42 -1
- data/lib/restspec/schema/types/basic_type.rb +62 -0
- data/lib/restspec/schema/types/boolean_type.rb +10 -0
- data/lib/restspec/schema/types/date_type.rb +12 -0
- data/lib/restspec/schema/types/datetime_type.rb +16 -0
- data/lib/restspec/schema/types/decimal_string_type.rb +16 -5
- data/lib/restspec/schema/types/decimal_type.rb +17 -1
- data/lib/restspec/schema/types/embedded_schema_type.rb +39 -8
- data/lib/restspec/schema/types/hash_type.rb +51 -12
- data/lib/restspec/schema/types/integer_type.rb +12 -1
- data/lib/restspec/schema/types/null_type.rb +7 -0
- data/lib/restspec/schema/types/one_of_type.rb +18 -0
- data/lib/restspec/schema/types/schema_id_type.rb +14 -17
- data/lib/restspec/schema/types/string_type.rb +9 -0
- data/lib/restspec/schema/types/type_methods.rb +32 -0
- data/lib/restspec/schema/types.rb +1 -18
- data/lib/restspec/shortcuts.rb +10 -0
- data/lib/restspec/stores/endpoint_store.rb +27 -2
- data/lib/restspec/stores/namespace_store.rb +23 -4
- data/lib/restspec/stores/schema_store.rb +15 -0
- data/lib/restspec/values/status_code.rb +16 -1
- data/lib/restspec/version.rb +1 -1
- data/lib/restspec.rb +2 -0
- data/restspec.gemspec +2 -0
- data/spec/restspec/endpoints/dsl_spec.rb +32 -19
- data/spec/restspec/endpoints/endpoint_spec.rb +20 -43
- data/spec/restspec/endpoints/namespace_spec.rb +0 -7
- data/spec/restspec/endpoints/request_spec.rb +33 -0
- data/spec/restspec/schema/attribute_spec.rb +44 -0
- data/spec/restspec/schema/checker_spec.rb +57 -0
- data/spec/restspec/schema/dsl_spec.rb +1 -1
- data/spec/restspec/schema/schema_spec.rb +15 -0
- data/spec/restspec/schema/types/basic_type_spec.rb +2 -2
- data/spec/restspec/schema/types/decimal_string_type_spec.rb +56 -0
- data/spec/restspec/schema/types/decimal_type_spec.rb +25 -0
- data/spec/restspec/schema/types/embedded_schema_type_spec.rb +32 -0
- data/spec/restspec/schema/types/hash_type_spec.rb +39 -0
- data/spec/restspec/schema/types/integer_type_spec.rb +28 -0
- data/spec/restspec/schema/types/one_of_type_spec.rb +21 -0
- data/spec/restspec/stores/endpoint_store_spec.rb +62 -0
- metadata +63 -10
- 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
|
-
|
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(
|
6
|
-
|
7
|
-
|
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
|
-
|
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
|
-
|
9
|
-
|
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
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
17
|
-
|
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(
|
6
|
-
|
7
|
-
|
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
|
-
|
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
|
-
|
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.
|
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
|
-
|
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'
|
data/lib/restspec/shortcuts.rb
CHANGED
@@ -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
|
-
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/restspec/version.rb
CHANGED
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"
|