restspec 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +21 -0
- data/.gitignore +23 -0
- data/.rspec +4 -0
- data/Gemfile +4 -0
- data/Guardfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +188 -0
- data/ROADMAP.md +11 -0
- data/Rakefile +20 -0
- data/bin/restspec +54 -0
- data/bin/templates/Gemfile +3 -0
- data/bin/templates/custom_macros.rb +3 -0
- data/bin/templates/restspec_config.rb +10 -0
- data/bin/templates/spec_helper.rb +19 -0
- data/docs/endpoints.md +200 -0
- data/docs/helpers.md +40 -0
- data/docs/macros.md +140 -0
- data/docs/matchers.md +38 -0
- data/docs/schemas.md +28 -0
- data/docs/tutorial.md +477 -0
- data/docs/types.md +134 -0
- data/examples/store-api-tests/.rspec +3 -0
- data/examples/store-api-tests/Gemfile +4 -0
- data/examples/store-api-tests/Gemfile.lock +70 -0
- data/examples/store-api-tests/spec/api/category_spec.rb +23 -0
- data/examples/store-api-tests/spec/api/product_spec.rb +55 -0
- data/examples/store-api-tests/spec/api/restspec/endpoints.rb +39 -0
- data/examples/store-api-tests/spec/api/restspec/requirements.rb +0 -0
- data/examples/store-api-tests/spec/api/restspec/restspec_config.rb +6 -0
- data/examples/store-api-tests/spec/api/restspec/schemas.rb +11 -0
- data/examples/store-api-tests/spec/spec_helper.rb +19 -0
- data/examples/store-api-tests/spec/support/custom_macros.rb +3 -0
- data/examples/store-api-tests/spec/support/custom_matchers.rb +0 -0
- data/examples/store-api/.editorconfig +24 -0
- data/examples/store-api/.rbenv-vars.example +3 -0
- data/examples/store-api/.rspec +4 -0
- data/examples/store-api/.ruby-version +1 -0
- data/examples/store-api/Gemfile +58 -0
- data/examples/store-api/Gemfile.lock +216 -0
- data/examples/store-api/Guardfile +39 -0
- data/examples/store-api/README.md +1 -0
- data/examples/store-api/Rakefile +6 -0
- data/examples/store-api/app/assets/images/.keep +0 -0
- data/examples/store-api/app/assets/javascripts/application.js +16 -0
- data/examples/store-api/app/assets/javascripts/categories.js.coffee +3 -0
- data/examples/store-api/app/assets/javascripts/products.js.coffee +3 -0
- data/examples/store-api/app/assets/stylesheets/application.css +15 -0
- data/examples/store-api/app/assets/stylesheets/categories.css.scss +3 -0
- data/examples/store-api/app/assets/stylesheets/products.css.scss +3 -0
- data/examples/store-api/app/assets/stylesheets/scaffolds.css.scss +69 -0
- data/examples/store-api/app/controllers/application_controller.rb +5 -0
- data/examples/store-api/app/controllers/categories_controller.rb +74 -0
- data/examples/store-api/app/controllers/concerns/.keep +0 -0
- data/examples/store-api/app/controllers/products_controller.rb +74 -0
- data/examples/store-api/app/helpers/application_helper.rb +2 -0
- data/examples/store-api/app/helpers/categories_helper.rb +2 -0
- data/examples/store-api/app/helpers/products_helper.rb +2 -0
- data/examples/store-api/app/mailers/.keep +0 -0
- data/examples/store-api/app/models/.keep +0 -0
- data/examples/store-api/app/models/category.rb +2 -0
- data/examples/store-api/app/models/concerns/.keep +0 -0
- data/examples/store-api/app/models/product.rb +3 -0
- data/examples/store-api/app/views/categories/_form.html.erb +21 -0
- data/examples/store-api/app/views/categories/edit.html.erb +6 -0
- data/examples/store-api/app/views/categories/index.html.erb +25 -0
- data/examples/store-api/app/views/categories/index.json.jbuilder +4 -0
- data/examples/store-api/app/views/categories/new.html.erb +5 -0
- data/examples/store-api/app/views/categories/show.html.erb +9 -0
- data/examples/store-api/app/views/categories/show.json.jbuilder +1 -0
- data/examples/store-api/app/views/layouts/application.html.erb +14 -0
- data/examples/store-api/app/views/products/_form.html.erb +29 -0
- data/examples/store-api/app/views/products/edit.html.erb +6 -0
- data/examples/store-api/app/views/products/index.html.erb +29 -0
- data/examples/store-api/app/views/products/index.json.jbuilder +4 -0
- data/examples/store-api/app/views/products/new.html.erb +5 -0
- data/examples/store-api/app/views/products/show.html.erb +19 -0
- data/examples/store-api/app/views/products/show.json.jbuilder +6 -0
- data/examples/store-api/bin/bundle +3 -0
- data/examples/store-api/bin/guard +16 -0
- data/examples/store-api/bin/rails +8 -0
- data/examples/store-api/bin/rake +8 -0
- data/examples/store-api/bin/spring +18 -0
- data/examples/store-api/config.ru +4 -0
- data/examples/store-api/config/application.rb +30 -0
- data/examples/store-api/config/boot.rb +4 -0
- data/examples/store-api/config/database.yml +25 -0
- data/examples/store-api/config/environment.rb +5 -0
- data/examples/store-api/config/environments/development.rb +37 -0
- data/examples/store-api/config/environments/production.rb +78 -0
- data/examples/store-api/config/environments/test.rb +39 -0
- data/examples/store-api/config/initializers/assets.rb +8 -0
- data/examples/store-api/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/store-api/config/initializers/cookies_serializer.rb +3 -0
- data/examples/store-api/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/store-api/config/initializers/inflections.rb +16 -0
- data/examples/store-api/config/initializers/mime_types.rb +4 -0
- data/examples/store-api/config/initializers/session_store.rb +3 -0
- data/examples/store-api/config/initializers/wrap_parameters.rb +14 -0
- data/examples/store-api/config/locales/en.yml +23 -0
- data/examples/store-api/config/routes.rb +59 -0
- data/examples/store-api/config/secrets.yml +22 -0
- data/examples/store-api/db/migrate/20141205154816_create_products.rb +11 -0
- data/examples/store-api/db/migrate/20141205171104_create_categories.rb +9 -0
- data/examples/store-api/db/migrate/20141205171140_add_category_id_to_products.rb +5 -0
- data/examples/store-api/db/schema.rb +31 -0
- data/examples/store-api/db/seeds.rb +7 -0
- data/examples/store-api/lib/assets/.keep +0 -0
- data/examples/store-api/lib/tasks/.keep +0 -0
- data/examples/store-api/log/.keep +0 -0
- data/examples/store-api/public/404.html +67 -0
- data/examples/store-api/public/422.html +67 -0
- data/examples/store-api/public/500.html +66 -0
- data/examples/store-api/public/favicon.ico +0 -0
- data/examples/store-api/public/robots.txt +5 -0
- data/examples/store-api/spec/controllers/categories_controller_spec.rb +159 -0
- data/examples/store-api/spec/controllers/products_controller_spec.rb +159 -0
- data/examples/store-api/spec/factories/categories.rb +6 -0
- data/examples/store-api/spec/factories/products.rb +8 -0
- data/examples/store-api/spec/helpers/categories_helper_spec.rb +15 -0
- data/examples/store-api/spec/helpers/products_helper_spec.rb +15 -0
- data/examples/store-api/spec/models/category_spec.rb +5 -0
- data/examples/store-api/spec/models/product_spec.rb +5 -0
- data/examples/store-api/spec/rails_helper.rb +50 -0
- data/examples/store-api/spec/requests/categories_spec.rb +10 -0
- data/examples/store-api/spec/requests/products_spec.rb +10 -0
- data/examples/store-api/spec/routing/categories_routing_spec.rb +35 -0
- data/examples/store-api/spec/routing/products_routing_spec.rb +35 -0
- data/examples/store-api/spec/spec_helper.rb +85 -0
- data/examples/store-api/spec/views/categories/edit.html.erb_spec.rb +18 -0
- data/examples/store-api/spec/views/categories/index.html.erb_spec.rb +19 -0
- data/examples/store-api/spec/views/categories/new.html.erb_spec.rb +18 -0
- data/examples/store-api/spec/views/categories/show.html.erb_spec.rb +14 -0
- data/examples/store-api/spec/views/products/edit.html.erb_spec.rb +24 -0
- data/examples/store-api/spec/views/products/index.html.erb_spec.rb +25 -0
- data/examples/store-api/spec/views/products/new.html.erb_spec.rb +24 -0
- data/examples/store-api/spec/views/products/show.html.erb_spec.rb +18 -0
- data/examples/store-api/vendor/assets/javascripts/.keep +0 -0
- data/examples/store-api/vendor/assets/stylesheets/.keep +0 -0
- data/lib/restspec.rb +38 -0
- data/lib/restspec/configuration.rb +43 -0
- data/lib/restspec/endpoints/dsl.rb +142 -0
- data/lib/restspec/endpoints/endpoint.rb +135 -0
- data/lib/restspec/endpoints/namespace.rb +89 -0
- data/lib/restspec/endpoints/network.rb +39 -0
- data/lib/restspec/endpoints/request.rb +11 -0
- data/lib/restspec/endpoints/response.rb +53 -0
- data/lib/restspec/requirements/dsl.rb +10 -0
- data/lib/restspec/requirements/requirement.rb +59 -0
- data/lib/restspec/rspec/api_helpers.rb +64 -0
- data/lib/restspec/rspec/api_macros.rb +126 -0
- data/lib/restspec/rspec/extras.rb +2 -0
- data/lib/restspec/rspec/matchers/api_matchers.rb +6 -0
- data/lib/restspec/rspec/matchers/be_like_schema.rb +18 -0
- data/lib/restspec/rspec/matchers/be_like_schema_array.rb +18 -0
- data/lib/restspec/rspec/matchers/have_header.rb +47 -0
- data/lib/restspec/rspec/matchers/have_status.rb +17 -0
- data/lib/restspec/rspec/matchers/include_where.rb +14 -0
- data/lib/restspec/rspec/shared_examples.rb +12 -0
- data/lib/restspec/schema/attribute.rb +31 -0
- data/lib/restspec/schema/attribute_example.rb +21 -0
- data/lib/restspec/schema/checker.rb +73 -0
- data/lib/restspec/schema/dsl.rb +36 -0
- data/lib/restspec/schema/schema.rb +21 -0
- data/lib/restspec/schema/schema_example.rb +28 -0
- data/lib/restspec/schema/types.rb +35 -0
- data/lib/restspec/schema/types/array_type.rb +34 -0
- data/lib/restspec/schema/types/basic_type.rb +35 -0
- data/lib/restspec/schema/types/boolean_type.rb +11 -0
- data/lib/restspec/schema/types/decimal_string_type.rb +32 -0
- data/lib/restspec/schema/types/decimal_type.rb +14 -0
- data/lib/restspec/schema/types/embedded_schema_type.rb +28 -0
- data/lib/restspec/schema/types/hash_type.rb +25 -0
- data/lib/restspec/schema/types/integer_type.rb +11 -0
- data/lib/restspec/schema/types/null_type.rb +11 -0
- data/lib/restspec/schema/types/one_of_type.rb +21 -0
- data/lib/restspec/schema/types/schema_id_type.rb +88 -0
- data/lib/restspec/schema/types/string_type.rb +11 -0
- data/lib/restspec/shortcuts.rb +8 -0
- data/lib/restspec/stores/endpoint_store.rb +25 -0
- data/lib/restspec/stores/namespace_store.rb +20 -0
- data/lib/restspec/stores/schema_store.rb +19 -0
- data/lib/restspec/values/status_code.rb +13 -0
- data/lib/restspec/values/super_hash.rb +12 -0
- data/lib/restspec/version.rb +3 -0
- data/restspec.gemspec +37 -0
- data/spec/restspec/endpoints/dsl_spec.rb +269 -0
- data/spec/restspec/endpoints/endpoint_spec.rb +146 -0
- data/spec/restspec/endpoints/namespace_spec.rb +143 -0
- data/spec/restspec/endpoints/response_spec.rb +49 -0
- data/spec/restspec/schema/attribute_example_spec.rb +35 -0
- data/spec/restspec/schema/dsl_spec.rb +78 -0
- data/spec/restspec/schema/schema_example_spec.rb +40 -0
- data/spec/restspec/schema/schema_spec.rb +11 -0
- data/spec/restspec/schema/types/array_type_spec.rb +56 -0
- data/spec/restspec/schema/types/basic_type_spec.rb +62 -0
- data/spec/restspec/schema/types/boolean_type_spec.rb +26 -0
- data/spec/restspec/schema/types/null_type_spec.rb +25 -0
- data/spec/restspec/schema/types/string_type_spec.rb +26 -0
- data/spec/restspec/values/status_code_spec.rb +13 -0
- data/spec/spec_helper.rb +23 -0
- metadata +484 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
RSpec.describe "products/show", :type => :view do
|
4
|
+
before(:each) do
|
5
|
+
@product = assign(:product, Product.create!(
|
6
|
+
:name => "Name",
|
7
|
+
:code => "Code",
|
8
|
+
:price => "9.99"
|
9
|
+
))
|
10
|
+
end
|
11
|
+
|
12
|
+
it "renders attributes in <p>" do
|
13
|
+
render
|
14
|
+
expect(rendered).to match(/Name/)
|
15
|
+
expect(rendered).to match(/Code/)
|
16
|
+
expect(rendered).to match(/9.99/)
|
17
|
+
end
|
18
|
+
end
|
File without changes
|
File without changes
|
data/lib/restspec.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require "restspec/version"
|
2
|
+
|
3
|
+
module Restspec
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'active_support/core_ext/object'
|
7
|
+
|
8
|
+
require "restspec/values/status_code"
|
9
|
+
require "restspec/values/super_hash"
|
10
|
+
|
11
|
+
require "restspec/configuration"
|
12
|
+
require "restspec/stores/namespace_store"
|
13
|
+
require "restspec/stores/endpoint_store"
|
14
|
+
require "restspec/stores/schema_store"
|
15
|
+
require "restspec/shortcuts"
|
16
|
+
|
17
|
+
require "restspec/schema/checker"
|
18
|
+
require "restspec/schema/types"
|
19
|
+
require "restspec/schema/attribute"
|
20
|
+
require "restspec/schema/attribute_example"
|
21
|
+
require "restspec/schema/schema_example"
|
22
|
+
require "restspec/schema/schema"
|
23
|
+
require "restspec/schema/dsl"
|
24
|
+
|
25
|
+
require "restspec/endpoints/dsl"
|
26
|
+
require "restspec/endpoints/request"
|
27
|
+
require "restspec/endpoints/response"
|
28
|
+
require "restspec/endpoints/network"
|
29
|
+
require "restspec/endpoints/endpoint"
|
30
|
+
require "restspec/endpoints/namespace"
|
31
|
+
|
32
|
+
require "restspec/requirements/dsl"
|
33
|
+
require "restspec/requirements/requirement"
|
34
|
+
|
35
|
+
require "restspec/rspec/extras"
|
36
|
+
require "restspec/rspec/api_helpers"
|
37
|
+
require "restspec/rspec/api_macros"
|
38
|
+
require "restspec/rspec/shared_examples"
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'active_support/configurable'
|
2
|
+
|
3
|
+
module Restspec
|
4
|
+
include ActiveSupport::Configurable
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def configure
|
8
|
+
config.request = OpenStruct.new(headers: {})
|
9
|
+
config.request.headers['Content-Type'] = 'application/json'
|
10
|
+
config.request.headers['Accept'] = 'application/json'
|
11
|
+
|
12
|
+
config.custom = OpenStruct.new
|
13
|
+
|
14
|
+
yield config
|
15
|
+
|
16
|
+
populate_stores
|
17
|
+
end
|
18
|
+
|
19
|
+
def populate_stores
|
20
|
+
load_schemas
|
21
|
+
load_endpoint_definition
|
22
|
+
load_requirement_definition
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def load_schemas
|
28
|
+
eval_file Schema::DSL.new, config.schema_definition
|
29
|
+
end
|
30
|
+
|
31
|
+
def load_endpoint_definition
|
32
|
+
eval_file Endpoints::DSL.new, config.endpoints_definition
|
33
|
+
end
|
34
|
+
|
35
|
+
def load_requirement_definition
|
36
|
+
eval_file Requirements::DSL.new, config.requirements_definition
|
37
|
+
end
|
38
|
+
|
39
|
+
def eval_file(object, file_name)
|
40
|
+
object.instance_eval(File.read(file_name)) if file_name.present?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
3
|
+
module Restspec
|
4
|
+
module Endpoints
|
5
|
+
HTTP_METHODS = [:get, :post, :put, :patch, :delete, :head]
|
6
|
+
|
7
|
+
class DSL
|
8
|
+
def namespace(name, base_path: nil, &block)
|
9
|
+
namespace = Namespace.create(name.to_s)
|
10
|
+
namespace.base_path = base_path
|
11
|
+
namespace_dsl = NamespaceDSL.new(namespace)
|
12
|
+
namespace_dsl.instance_eval(&block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def resource(name, options = {}, &block)
|
16
|
+
namespace name, base_path: (options[:base_path] || "/#{name}") do
|
17
|
+
if self.namespace.schema_name.blank?
|
18
|
+
schema_name = name.to_s.singularize
|
19
|
+
schema(schema_name.to_sym)
|
20
|
+
end
|
21
|
+
|
22
|
+
instance_eval(&block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class NamespaceDSL
|
28
|
+
attr_accessor :namespace, :endpoint_base_path, :resource_endpoint_base_path, :common_endpoints_config_block
|
29
|
+
|
30
|
+
def initialize(namespace)
|
31
|
+
self.namespace = namespace
|
32
|
+
self.resource_endpoint_base_path = ''
|
33
|
+
end
|
34
|
+
|
35
|
+
def endpoint(name, &block)
|
36
|
+
endpoint = Endpoint.new(name)
|
37
|
+
endpoint_dsl = EndpointDSL.new(endpoint)
|
38
|
+
namespace.add_endpoint(endpoint)
|
39
|
+
|
40
|
+
endpoint_dsl.instance_eval(&block)
|
41
|
+
endpoint_dsl.instance_eval(&common_endpoints_config_block)
|
42
|
+
|
43
|
+
Restspec::EndpointStore.store(endpoint)
|
44
|
+
end
|
45
|
+
|
46
|
+
HTTP_METHODS.each do |http_method|
|
47
|
+
define_method(http_method) do |name, path = '', &block|
|
48
|
+
endpoint(name) do
|
49
|
+
public_send(http_method, path)
|
50
|
+
instance_eval(&block) if block.present?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def member(base_path: nil, identifier_name: 'id', &block)
|
56
|
+
member_namespace = namespace.add_anonymous_children_namespace
|
57
|
+
member_namespace.base_path = base_path || "/:#{identifier_name}"
|
58
|
+
NamespaceDSL.new(member_namespace).instance_eval(&block)
|
59
|
+
end
|
60
|
+
|
61
|
+
def collection(base_path: nil, &block)
|
62
|
+
collection_namespace = namespace.add_anonymous_children_namespace
|
63
|
+
collection_namespace.base_path = base_path
|
64
|
+
NamespaceDSL.new(collection_namespace).instance_eval(&block)
|
65
|
+
end
|
66
|
+
|
67
|
+
def schema(name, schema_extensions = {})
|
68
|
+
namespace.schema_name = name
|
69
|
+
namespace.schema_extensions = schema_extensions
|
70
|
+
end
|
71
|
+
|
72
|
+
def all(&endpoints_config)
|
73
|
+
self.common_endpoints_config_block = endpoints_config
|
74
|
+
end
|
75
|
+
|
76
|
+
def url_param(param, &value_or_example_block)
|
77
|
+
all do
|
78
|
+
url_param(param, &value_or_example_block)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def common_endpoints_config_block
|
85
|
+
@common_endpoints_config_block ||= (Proc.new {})
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class EndpointDSL < Struct.new(:endpoint)
|
90
|
+
def method(method)
|
91
|
+
endpoint.method = method
|
92
|
+
end
|
93
|
+
|
94
|
+
def path(path)
|
95
|
+
endpoint.path = path
|
96
|
+
end
|
97
|
+
|
98
|
+
def schema(name, schema_extensions = {})
|
99
|
+
endpoint.schema_name = name
|
100
|
+
endpoint.schema_extensions = schema_extensions
|
101
|
+
end
|
102
|
+
|
103
|
+
def headers
|
104
|
+
endpoint.headers
|
105
|
+
end
|
106
|
+
|
107
|
+
def url_param(param, &value_or_type_block)
|
108
|
+
endpoint.add_url_param_block(param) do
|
109
|
+
value_or_type_context = ValueOrTypeContext.new
|
110
|
+
value_or_type = value_or_type_context.instance_eval(&value_or_type_block)
|
111
|
+
|
112
|
+
if value_or_type.is_a?(Restspec::Schema::Types::BasicType)
|
113
|
+
attribute = if endpoint.schema && endpoint.schema.attributes[param]
|
114
|
+
endpoint.schema.attributes[param]
|
115
|
+
else
|
116
|
+
Restspec::Schema::Attribute.new(param, value_or_type_context.integer)
|
117
|
+
end
|
118
|
+
|
119
|
+
value_or_type.example_for(attribute)
|
120
|
+
else
|
121
|
+
value_or_type
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
HTTP_METHODS.each do |http_method|
|
127
|
+
define_method(http_method) do |path|
|
128
|
+
self.method http_method
|
129
|
+
self.path path
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class ValueOrTypeContext
|
135
|
+
Restspec::Schema::Types::ALL.each do |type_name, type_class|
|
136
|
+
define_method(type_name) do |options = {}|
|
137
|
+
type_class.new(options)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module Restspec
|
4
|
+
module Endpoints
|
5
|
+
class Endpoint < Struct.new(:name)
|
6
|
+
attr_accessor :method, :path, :namespace, :raw_url_params, :schema_extensions
|
7
|
+
attr_writer :schema_name
|
8
|
+
attr_reader :last_response, :last_request
|
9
|
+
|
10
|
+
PARAM_INTERPOLATION_REGEX = /:([\w]+)/
|
11
|
+
|
12
|
+
def execute(body: {}, url_params: {}, query_params: {})
|
13
|
+
full_url = build_full_url(url_params, query_params)
|
14
|
+
request = Request.new(method, full_url, full_headers, body)
|
15
|
+
|
16
|
+
Network.request(request).tap do |response|
|
17
|
+
self.last_request = inject_self_into(response, :endpoint)
|
18
|
+
self.last_request = inject_self_into(request, :endpoint)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute_once(body: {}, url_params: {}, query_params: {}, before: ->{ })
|
23
|
+
@executed_response ||= begin
|
24
|
+
before.call
|
25
|
+
execute(body: body, url_params: url_params, query_params: query_params)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def full_name
|
30
|
+
[namespace.try(:name), name].compact.join("/")
|
31
|
+
end
|
32
|
+
|
33
|
+
def schema_name
|
34
|
+
@schema_name || namespace.try(:schema_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def schema
|
38
|
+
@schema ||= begin
|
39
|
+
found_schema = schema_from_store
|
40
|
+
if found_schema.present?
|
41
|
+
found_schema.clone.extend_with(schema_extensions || {})
|
42
|
+
else
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def full_path
|
49
|
+
if namespace && in_member_or_collection?
|
50
|
+
"#{namespace.full_base_path}#{path}"
|
51
|
+
else
|
52
|
+
path
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def headers
|
57
|
+
@headers ||= {}
|
58
|
+
end
|
59
|
+
|
60
|
+
def url_params
|
61
|
+
@url_params ||= Restspec::Values::SuperHash.new(calculate_url_params)
|
62
|
+
end
|
63
|
+
|
64
|
+
def add_url_param_block(param, &block)
|
65
|
+
raw_url_params[param] = Proc.new(&block)
|
66
|
+
end
|
67
|
+
|
68
|
+
def executed_url
|
69
|
+
last_request.url
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
attr_writer :last_response, :last_request
|
75
|
+
|
76
|
+
def schema_from_store
|
77
|
+
Restspec::SchemaStore.get(schema_name)
|
78
|
+
end
|
79
|
+
|
80
|
+
def inject_self_into(object, property)
|
81
|
+
object.tap { object.send(:"#{property}=", self) }
|
82
|
+
end
|
83
|
+
|
84
|
+
def build_full_url(url_params, query_params)
|
85
|
+
full_url_params = self.url_params.merge(Values::SuperHash.new(url_params))
|
86
|
+
build_url(full_url_params, query_params)
|
87
|
+
end
|
88
|
+
|
89
|
+
def raw_url_params
|
90
|
+
@raw_url_params ||= Restspec::Values::SuperHash.new
|
91
|
+
end
|
92
|
+
|
93
|
+
def in_member_or_collection?
|
94
|
+
namespace.anonymous?
|
95
|
+
end
|
96
|
+
|
97
|
+
def calculate_url_params
|
98
|
+
raw_url_params.inject({}) do |hash, (key, value)|
|
99
|
+
real_value = if value.respond_to?(:call)
|
100
|
+
value.call
|
101
|
+
else
|
102
|
+
value
|
103
|
+
end
|
104
|
+
|
105
|
+
hash.merge(key.to_sym => real_value)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def build_url(full_url_params, query_params)
|
110
|
+
query_string = query_params.to_param
|
111
|
+
full_query_string = query_string.present? ? "?#{query_string}" : ""
|
112
|
+
|
113
|
+
base_url + path_from_params(full_url_params) + full_query_string
|
114
|
+
end
|
115
|
+
|
116
|
+
def path_from_params(url_params)
|
117
|
+
full_path.gsub(PARAM_INTERPOLATION_REGEX) do
|
118
|
+
url_params[$1] || url_params[$1.to_sym]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def full_headers
|
123
|
+
config_headers.merge(headers)
|
124
|
+
end
|
125
|
+
|
126
|
+
def config_headers
|
127
|
+
Restspec.config.try(:request).try(:headers) || {}
|
128
|
+
end
|
129
|
+
|
130
|
+
def base_url
|
131
|
+
@base_url ||= (Restspec.config.base_url || '')
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Restspec
|
2
|
+
module Endpoints
|
3
|
+
class Namespace
|
4
|
+
attr_accessor :base_path, :parent_namespace, :children_namespaces, :schema_extensions
|
5
|
+
attr_writer :schema_name
|
6
|
+
attr_reader :endpoints
|
7
|
+
|
8
|
+
def self.create(name = '')
|
9
|
+
namespace = new(name)
|
10
|
+
Stores::NamespaceStore.store(namespace)
|
11
|
+
namespace
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(name = '')
|
15
|
+
self.name = name
|
16
|
+
self.endpoints = []
|
17
|
+
self.children_namespaces = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_anonymous_children_namespace
|
21
|
+
anonymous_namespace = Namespace.create
|
22
|
+
anonymous_namespace.parent_namespace = self
|
23
|
+
children_namespaces << anonymous_namespace
|
24
|
+
anonymous_namespace
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_endpoint(endpoint)
|
28
|
+
endpoint.namespace = self
|
29
|
+
endpoints << endpoint
|
30
|
+
endpoint
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_endpoint(endpoint_name)
|
34
|
+
search_internal_endpoint(endpoint_name) || search_child_endpoint(endpoint_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def top_level_namespace?
|
38
|
+
parent_namespace.nil?
|
39
|
+
end
|
40
|
+
|
41
|
+
def full_base_path
|
42
|
+
if top_level_namespace?
|
43
|
+
base_path
|
44
|
+
else
|
45
|
+
parent_namespace.full_base_path + base_path
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def schema_name
|
50
|
+
@schema_name || parent_namespace.try(:schema_name)
|
51
|
+
end
|
52
|
+
|
53
|
+
def name
|
54
|
+
if top_level_namespace?
|
55
|
+
@name
|
56
|
+
else
|
57
|
+
[parent_namespace.name, @name].reject(&:blank?).join('/')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def anonymous?
|
62
|
+
@name.blank?
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
attr_writer :name, :endpoints
|
68
|
+
|
69
|
+
def search_internal_endpoint(endpoint_name)
|
70
|
+
endpoints.find do |endpoint|
|
71
|
+
endpoint.name == endpoint_name
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def search_child_endpoint(endpoint_name)
|
76
|
+
children_namespaces.each do |children_namespace|
|
77
|
+
child_endpoint = children_namespace.get_endpoint(endpoint_name)
|
78
|
+
return child_endpoint if child_endpoint.present?
|
79
|
+
end
|
80
|
+
|
81
|
+
return nil
|
82
|
+
end
|
83
|
+
|
84
|
+
def base_path
|
85
|
+
@base_path ||= ''
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|