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