rspec-api 0.4.0 → 0.5.0
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/lib/rspec-api.rb +1 -0
- data/lib/rspec-api/dsl.rb +40 -19
- data/lib/rspec-api/dsl/accepts.rb +46 -0
- data/lib/rspec-api/dsl/actions.rb +36 -0
- data/lib/rspec-api/dsl/attributes.rb +13 -0
- data/lib/rspec-api/dsl/requests.rb +78 -0
- data/lib/rspec-api/dsl/responses.rb +37 -0
- data/lib/rspec-api/fixtures/empty.rb +35 -0
- data/lib/rspec-api/fixtures/local.rb +50 -0
- data/lib/rspec-api/fixtures/remote.rb +82 -0
- data/lib/rspec-api/http_clients/empty.rb +14 -0
- data/lib/rspec-api/http_clients/local.rb +28 -0
- data/lib/rspec-api/{http/remote/route.rb → http_clients/remote.rb} +16 -8
- data/lib/rspec-api/version.rb +1 -1
- metadata +32 -21
- data/lib/rspec-api/dsl/request.rb +0 -5
- data/lib/rspec-api/dsl/request/body.rb +0 -85
- data/lib/rspec-api/dsl/request/headers.rb +0 -40
- data/lib/rspec-api/dsl/request/request.rb +0 -14
- data/lib/rspec-api/dsl/request/response.rb +0 -86
- data/lib/rspec-api/dsl/request/status.rb +0 -18
- data/lib/rspec-api/dsl/resource.rb +0 -68
- data/lib/rspec-api/dsl/route.rb +0 -135
- data/lib/rspec-api/http/local.rb +0 -11
- data/lib/rspec-api/http/local/request.rb +0 -15
- data/lib/rspec-api/http/local/route.rb +0 -12
- data/lib/rspec-api/http/remote.rb +0 -23
- data/lib/rspec-api/http/remote/request.rb +0 -15
- data/lib/rspec-api/http/remote/resource.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ca5599e96ba26d321698c09c88a338919c4bf8a
|
4
|
+
data.tar.gz: ae0a49475f6343996a3eb2313ecba068e20db34b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c26cdc3ffe743a93ee67be9567a2fcbf70810f54381c866b971626cd4a5961828fcfb56e0dceddeeea3e5a0b5ab08119a8aefb787262f7df3c9bc0aa8aacf4f1
|
7
|
+
data.tar.gz: 26b169c8bbaa0d2e9893b764bcfadcf9a187942a312dc6ca2fb17cb41391b4d153c1f65e94d74063a77a32b8249fe476619874b4f8b665c939a45337af8c4f95
|
data/lib/rspec-api.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rspec-api/dsl'
|
data/lib/rspec-api/dsl.rb
CHANGED
@@ -1,24 +1,45 @@
|
|
1
|
-
require 'rspec-api/dsl/
|
2
|
-
require 'rspec-api/dsl/
|
3
|
-
require 'rspec-api/dsl/
|
1
|
+
require 'rspec-api/dsl/accepts'
|
2
|
+
require 'rspec-api/dsl/actions'
|
3
|
+
require 'rspec-api/dsl/attributes'
|
4
4
|
|
5
|
-
module
|
5
|
+
module RSpecApi
|
6
|
+
module DSL
|
7
|
+
include Accepts
|
8
|
+
include Actions
|
9
|
+
include Attributes
|
10
|
+
include Fixtures
|
11
|
+
end
|
6
12
|
end
|
7
13
|
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
# RSpecApi provides methods to test RESTful APIs.
|
15
|
+
#
|
16
|
+
# To have these methods available in your RSpec ExampleGroups you have to
|
17
|
+
# tag the `describe` block with the `:rspec_api` metadata.
|
18
|
+
#
|
19
|
+
# describe "Artists", rspec_api: true do
|
20
|
+
# ... # here you can use `get`, `delete`, etc.
|
21
|
+
# end
|
22
|
+
RSpec.configuration.extend RSpecApi::DSL, rspec_api: true
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
+
# Alternatively, you replace `describe` with `resource`, for the same result:
|
25
|
+
#
|
26
|
+
#
|
27
|
+
# resource :artist do
|
28
|
+
# ... # same as before, here you can use `get`, `delete`, etc.
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
#
|
32
|
+
# `resource` is indeed the only top-level namespace RSpecApi method.
|
33
|
+
def resource(name, args = {}, &block)
|
34
|
+
args.merge! rspec_api: true
|
35
|
+
resources = (@resources ||= [])
|
36
|
+
resource = describe name.to_s.pluralize.humanize, args do
|
37
|
+
@resource = name
|
38
|
+
@resources = resources
|
39
|
+
@expectations = []
|
40
|
+
@expectations << {query_params: {}, status_expect: {status: 200}, body_expect: {attributes: {name: {type: :string}, website: {type: [:null, string: :url]}}}}
|
41
|
+
@attributes = {}
|
42
|
+
instance_exec &block
|
43
|
+
end
|
44
|
+
@resources << resource
|
24
45
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module RSpecApi
|
2
|
+
module DSL
|
3
|
+
module Accepts
|
4
|
+
|
5
|
+
def accepts_page(page_parameter)
|
6
|
+
any_page = 2
|
7
|
+
@expectations << {
|
8
|
+
query_params: {}.tap{|qp| qp[page_parameter] = any_page},
|
9
|
+
status_expect: {status: 200},
|
10
|
+
headers_expect: {has_prev_page: true}
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def accepts_sort(sort_parameter, options={})
|
15
|
+
@expectations << {
|
16
|
+
query_params: {sort: sort_parameter}.merge(options.fetch(:sort_if, {})),
|
17
|
+
before: create_fixture,
|
18
|
+
after: destroy_fixture,
|
19
|
+
status_expect: {status: 200},
|
20
|
+
body_expect: {sort: options.slice(:by, :verse)}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def accepts_callback(callback_parameter)
|
25
|
+
any_callback = 'a_callback'
|
26
|
+
@expectations << {
|
27
|
+
query_params: {}.tap{|qp| qp[callback_parameter] = any_callback},
|
28
|
+
status_expect: {status: 200},
|
29
|
+
body_expect: {callback: any_callback}
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def accepts_filter(filter_parameter, options={})
|
34
|
+
value = existing(options[:by])
|
35
|
+
@expectations << {
|
36
|
+
query_params: {}.tap{|qp| qp[filter_parameter] = value},
|
37
|
+
before: create_fixture,
|
38
|
+
after: destroy_fixture,
|
39
|
+
status_expect: {status: 200},
|
40
|
+
body_expect: {filter: options.slice(:by, :comparing_with).merge(value: value)}
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rspec-api/dsl/requests'
|
2
|
+
|
3
|
+
module RSpecApi
|
4
|
+
module DSL
|
5
|
+
module Actions
|
6
|
+
include RSpecApi::DSL::Fixtures
|
7
|
+
include RSpecApi::DSL::Requests
|
8
|
+
|
9
|
+
def self.define_action(action)
|
10
|
+
define_method action do |route, options = {}, &block|
|
11
|
+
expectations = @expectations
|
12
|
+
attributes = @attributes
|
13
|
+
authorization = @authorization
|
14
|
+
resource = @resource
|
15
|
+
collection = options[:collection]
|
16
|
+
describe "#{action.upcase} #{route}" do
|
17
|
+
@action = action
|
18
|
+
@route = route
|
19
|
+
@expectations = expectations
|
20
|
+
@attributes = attributes
|
21
|
+
@authorization = authorization
|
22
|
+
@collection = collection
|
23
|
+
@resource = resource
|
24
|
+
instance_eval &block
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
define_action :get
|
30
|
+
define_action :put
|
31
|
+
define_action :patch
|
32
|
+
define_action :post
|
33
|
+
define_action :delete
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module RSpecApi
|
2
|
+
module DSL
|
3
|
+
module Attributes
|
4
|
+
def has_attribute(name, options = {}, &block)
|
5
|
+
@attributes[name] = options
|
6
|
+
end
|
7
|
+
|
8
|
+
def attributes_of(resource)
|
9
|
+
@resources.find{|r| r.description == resource.to_s.pluralize.humanize}.instance_variable_get '@attributes'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'rspec-api/dsl/responses'
|
2
|
+
|
3
|
+
module RSpecApi
|
4
|
+
module DSL
|
5
|
+
module Requests
|
6
|
+
def my_collection_request(query_params = {}, &block)
|
7
|
+
@expectations.each do |options|
|
8
|
+
single_request(options.deep_merge(body_expect: {collection: true}, query_params: query_params), &block)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def respond_with(*args) # NOT THE TRUE ONE
|
13
|
+
request_with do
|
14
|
+
respond_with(*args)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def request_with(query_params = {}, &block)
|
19
|
+
if @collection
|
20
|
+
my_collection_request(query_params, &block)
|
21
|
+
else
|
22
|
+
single_request(query_params: query_params, &block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def single_request(options = {}, &block)
|
27
|
+
query_params = options.fetch(:query_params, {})
|
28
|
+
status_expect = options.fetch(:status_expect, {status: 200})
|
29
|
+
headers_expect = options.fetch(:headers_expect, {type: :json})
|
30
|
+
body_expect = options.fetch(:body_expect, {collection: false}) # Or maybe nothing
|
31
|
+
body_expect = body_expect.merge(attributes: @attributes) if @attributes
|
32
|
+
before_fun = options.fetch(:before, -> {})
|
33
|
+
after_fun = options.fetch(:after, -> {})
|
34
|
+
query = {authorization: @authorization, route_params: {}, action: @action, route: @route, query_params: query_params, status_expect: status_expect, headers_expect: headers_expect, body_expect: body_expect, before: before_fun, after: after_fun}
|
35
|
+
|
36
|
+
query_params.each do |k, v|
|
37
|
+
if v.is_a?(Hash) && v[:proc] && v[:value] # so we avoid getting the hash of the callback called :proc
|
38
|
+
query[:query_params][k] = v[:value]
|
39
|
+
if v[:proc] == :existing
|
40
|
+
query = query.merge before: create_fixture, after: destroy_fixture
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
my_real_request(query, &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
def my_real_request(query = {}, &block)
|
49
|
+
query[:before].call
|
50
|
+
|
51
|
+
query.fetch(:query_params, {}).each do |k, v|
|
52
|
+
query[:query_params][k] = v.is_a?(Proc) ? v.call : v
|
53
|
+
if query[:route].match "/:#{k}"
|
54
|
+
query[:route] = query[:route].gsub "/:#{k}", "/#{query[:query_params][k]}"
|
55
|
+
query[:route_params][k] = query[:query_params].delete k
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "with #{query[:route].is_a?(Proc) ? query[:route].call : query[:route]}#{" and #{query[:query_params]}" if query[:query_params].any?}" do
|
60
|
+
extend RSpecApi::DSL::Responses
|
61
|
+
extend RSpecApi::DSL::HttpClient
|
62
|
+
send_request query[:action], (query[:route].is_a?(Proc) ? query[:route].call : query[:route]), query[:query_params], query[:authorization]
|
63
|
+
@response = last_response
|
64
|
+
@status_expect = query.fetch :status_expect, {}
|
65
|
+
@headers_expect = query.fetch :headers_expect, {}
|
66
|
+
@body_expect = query.fetch :body_expect, {}
|
67
|
+
@route_params = query.fetch :route_params, {}
|
68
|
+
if @body_expect.fetch(:filter, {})[:value].is_a?(Hash) && @body_expect.fetch(:filter, {})[:value][:proc]
|
69
|
+
@body_expect[:filter][:value] = @body_expect[:filter][:value][:value].call
|
70
|
+
end
|
71
|
+
instance_exec &block
|
72
|
+
end
|
73
|
+
|
74
|
+
query[:after].call
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rspec-api/expectations'
|
2
|
+
|
3
|
+
module RSpecApi
|
4
|
+
module DSL
|
5
|
+
module Responses
|
6
|
+
include RSpecApi::Expectations::Resourceful
|
7
|
+
|
8
|
+
def respond_with(*args, &block)
|
9
|
+
if args.first.is_a?(Hash)
|
10
|
+
more_status_expect = args.first
|
11
|
+
more_headers_expect = {}
|
12
|
+
more_body_expect = {}
|
13
|
+
elsif args.first.is_a?(Array)
|
14
|
+
more_status_expect, more_headers_expect, more_body_expect = args
|
15
|
+
else
|
16
|
+
more_status_expect = {status: args.first}
|
17
|
+
more_headers_expect = {}
|
18
|
+
more_body_expect = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
all_expectations = @status_expect.merge(more_status_expect).merge(
|
22
|
+
@headers_expect).merge(more_headers_expect).merge(@body_expect).
|
23
|
+
merge(more_body_expect)
|
24
|
+
|
25
|
+
expect_resourceful(@response, all_expectations)
|
26
|
+
expect_custom(@response, @route_params, &block) if block_given?
|
27
|
+
end
|
28
|
+
|
29
|
+
def expect_custom(response, route_params, &block)
|
30
|
+
context 'matches custom expectations' do
|
31
|
+
# THE ONLY MISSING THING:
|
32
|
+
it { instance_exec response, route_params, &block }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module RSpecApi
|
2
|
+
module DSL
|
3
|
+
module Fixtures # rename to Fixtures
|
4
|
+
def existing(field)
|
5
|
+
# To be overriden
|
6
|
+
end
|
7
|
+
|
8
|
+
def unknown(field)
|
9
|
+
# To be overriden
|
10
|
+
end
|
11
|
+
|
12
|
+
def apply(method_name, options = {})
|
13
|
+
options[:to].merge(apply: method_name, value: -> { options[:to][:value].call.send method_name })
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid(options = {})
|
17
|
+
# TODO: Here change the description
|
18
|
+
options
|
19
|
+
end
|
20
|
+
|
21
|
+
def invalid(options = {})
|
22
|
+
# TODO: Here change the description
|
23
|
+
options
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_fixture
|
27
|
+
# To be overriden
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy_fixture
|
31
|
+
# To be overriden
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module RSpecApi
|
2
|
+
module DSL
|
3
|
+
module Fixtures # rename to Fixtures
|
4
|
+
def existing(field)
|
5
|
+
{field: field, proc: :existing, value: existing_value_for(field)}
|
6
|
+
end
|
7
|
+
|
8
|
+
def unknown(field)
|
9
|
+
{field: field, proc: :unknown, value: missing_value_for(field)}
|
10
|
+
end
|
11
|
+
|
12
|
+
def apply(method_name, options = {})
|
13
|
+
options[:to].merge(apply: method_name, value: -> { options[:to][:value].call.send method_name })
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid(options = {})
|
17
|
+
# TODO: Here change the description
|
18
|
+
options
|
19
|
+
end
|
20
|
+
|
21
|
+
def invalid(options = {})
|
22
|
+
# TODO: Here change the description
|
23
|
+
options
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_fixture
|
27
|
+
# TODO: Random values from attributes
|
28
|
+
-> {
|
29
|
+
model = @resource.to_s.classify.constantize
|
30
|
+
case @resource
|
31
|
+
when :artist then model.create! name: 'Madonna', website: 'http://www.example.com'
|
32
|
+
when :concert then model.create! where: 'Coachella', year: 2010
|
33
|
+
end
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def destroy_fixture
|
38
|
+
-> {@resource.to_s.classify.constantize.destroy_all}
|
39
|
+
end
|
40
|
+
|
41
|
+
def existing_value_for(field)
|
42
|
+
-> {@resource.to_s.classify.constantize.pluck(field).first}
|
43
|
+
end
|
44
|
+
|
45
|
+
def missing_value_for(field)
|
46
|
+
-> {-1}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module RSpecApi
|
2
|
+
module DSL
|
3
|
+
module Fixtures # rename to Fixtures
|
4
|
+
def existing(field)
|
5
|
+
{field: field, proc: :existing, value: existing_value_for(field)}
|
6
|
+
end
|
7
|
+
|
8
|
+
def unknown(field)
|
9
|
+
{field: field, proc: :unknown, value: missing_value_for(field)}
|
10
|
+
end
|
11
|
+
|
12
|
+
def apply(method_name, options = {})
|
13
|
+
options[:to].merge(apply: method_name, value: -> { options[:to][:value].call.send method_name })
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid(options = {})
|
17
|
+
# TODO: Here change the description
|
18
|
+
options
|
19
|
+
end
|
20
|
+
|
21
|
+
def invalid(options = {})
|
22
|
+
# TODO: Here change the description
|
23
|
+
options
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_fixture
|
27
|
+
# TODO: Nothing for now
|
28
|
+
-> { }
|
29
|
+
end
|
30
|
+
|
31
|
+
def destroy_fixture
|
32
|
+
# TODO: Nothing for now
|
33
|
+
-> { }
|
34
|
+
end
|
35
|
+
|
36
|
+
def existing_value_for(field)
|
37
|
+
value = case field
|
38
|
+
when :org then 'rspec-api'
|
39
|
+
when :user, :owner, :assignee then 'rspecapi'
|
40
|
+
when :repo then 'guinea-pig' # has heads, tails, pull, notes
|
41
|
+
when :gist_id then '7175672'
|
42
|
+
when :gist_comment_id then '937901'
|
43
|
+
|
44
|
+
when :blob_sha then 'f32932f7c927d86f57f56d703ac2ed100ceb0e47'
|
45
|
+
when :commit_sha then 'c98a37ea3b2759d0c43fb8abfa9abd3146938790'
|
46
|
+
when :tree_sha then 'ebca91692290192f50acc307af9fe26b2eab4274'
|
47
|
+
when :ref then 'heads/master'
|
48
|
+
when :starred_repo then 'rspec-expectations' # make it different from :repo
|
49
|
+
when :unstarred_repo then 'rspec-core' # make it different from :repo
|
50
|
+
when :starred_gist_id then 'e202e2fb143c54e5139a'
|
51
|
+
when :unstarred_gist_id then '8f2ef7e69ab79084d833'
|
52
|
+
when :someone_elses_gist_id then '4685e0bebbf05370abd6'
|
53
|
+
when :thread_id then '17915960'
|
54
|
+
when :id then '921225'
|
55
|
+
# NOTE: The following are confusing: they are used for filters, not value
|
56
|
+
# For instance, it's not that we must have an object with the following
|
57
|
+
# updated_at, we just use it for the since filter
|
58
|
+
when :updated_at then '2013-10-31T09:53:00Z' # TODO use helpers
|
59
|
+
# NOTE: Here's the confusion: :unread is used for the :all filter, but
|
60
|
+
# it has the reverse meaning: ?all=false will only show unread='true'
|
61
|
+
when :unread then 'false' # TODO use helpers
|
62
|
+
# NOTE: Here's more confusion: :reason is a string, but this is used for
|
63
|
+
# the boolean parameter participating:
|
64
|
+
# ?participating=true (default), only show reason = 'mention' or 'author'
|
65
|
+
# ?participating=false, show all reasons
|
66
|
+
when :reason then 'true' # TODO use helpers
|
67
|
+
end
|
68
|
+
-> { value }
|
69
|
+
end
|
70
|
+
|
71
|
+
def missing_value_for(field)
|
72
|
+
value = case field
|
73
|
+
when :user, :assignee then 'not-a-valid-user'
|
74
|
+
when :gist_id then 'not-a-valid-gist-id'
|
75
|
+
when :id then 'not-a-valid-id'
|
76
|
+
when :repo then 'not-a-valid-repo'
|
77
|
+
end
|
78
|
+
-> { value }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module RSpecApi
|
2
|
+
module DSL
|
3
|
+
module HttpClient
|
4
|
+
def send_request(verb, route, body, authorization)
|
5
|
+
# To be overriden
|
6
|
+
end
|
7
|
+
|
8
|
+
def last_response
|
9
|
+
# To be overriden. status MUST be a number, headers MUST be a hash
|
10
|
+
OpenStruct.new status: nil, headers: {} # body: nil,
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.expand_path("../../../../spec/dummy/config/environment.rb", __FILE__)
|
2
|
+
require 'rspec/rails'
|
3
|
+
require 'rack/test'
|
4
|
+
|
5
|
+
def app
|
6
|
+
Rails.application
|
7
|
+
end
|
8
|
+
|
9
|
+
module RSpecApi
|
10
|
+
module DSL
|
11
|
+
module HttpClient
|
12
|
+
include Rack::Test::Methods
|
13
|
+
|
14
|
+
def ciao
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
def send_request(verb, route, body, authorization)
|
19
|
+
header 'Accept', 'application/json'
|
20
|
+
send verb, route, body
|
21
|
+
end
|
22
|
+
|
23
|
+
def response
|
24
|
+
last_response
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,9 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware' # TODO: use autoload, we only need EncodeJson
|
3
|
+
require 'faraday-http-cache'
|
4
|
+
require 'logger'
|
5
5
|
|
6
|
-
|
6
|
+
module Authorize
|
7
|
+
def authorize_with(options = {})
|
8
|
+
@authorization = options
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module RSpecApi
|
13
|
+
module DSL
|
14
|
+
module HttpClient
|
15
|
+
def send_request(verb, route, body, authorization)
|
7
16
|
logger = Logger.new 'log/faraday.log'
|
8
17
|
|
9
18
|
conn = Faraday.new 'https://api.github.com/' do |c| # TODO: Pass host as a parameter
|
@@ -23,9 +32,8 @@ module Http
|
|
23
32
|
end
|
24
33
|
end
|
25
34
|
|
26
|
-
def
|
27
|
-
|
28
|
-
self.class.metadata[:rspec_api][:authorization]
|
35
|
+
def last_response
|
36
|
+
@last_response
|
29
37
|
end
|
30
38
|
end
|
31
39
|
end
|
data/lib/rspec-api/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- claudiob
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -28,16 +28,30 @@ dependencies:
|
|
28
28
|
name: rspec-api-matchers
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 0.5.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 0.5.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-api-expectations
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.5.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.5.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rack
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -257,23 +271,20 @@ executables: []
|
|
257
271
|
extensions: []
|
258
272
|
extra_rdoc_files: []
|
259
273
|
files:
|
260
|
-
- lib/rspec-api/dsl/
|
261
|
-
- lib/rspec-api/dsl/
|
262
|
-
- lib/rspec-api/dsl/
|
263
|
-
- lib/rspec-api/dsl/
|
264
|
-
- lib/rspec-api/dsl/
|
265
|
-
- lib/rspec-api/dsl/request.rb
|
266
|
-
- lib/rspec-api/dsl/resource.rb
|
267
|
-
- lib/rspec-api/dsl/route.rb
|
274
|
+
- lib/rspec-api/dsl/accepts.rb
|
275
|
+
- lib/rspec-api/dsl/actions.rb
|
276
|
+
- lib/rspec-api/dsl/attributes.rb
|
277
|
+
- lib/rspec-api/dsl/requests.rb
|
278
|
+
- lib/rspec-api/dsl/responses.rb
|
268
279
|
- lib/rspec-api/dsl.rb
|
269
|
-
- lib/rspec-api/
|
270
|
-
- lib/rspec-api/
|
271
|
-
- lib/rspec-api/
|
272
|
-
- lib/rspec-api/
|
273
|
-
- lib/rspec-api/
|
274
|
-
- lib/rspec-api/
|
275
|
-
- lib/rspec-api/http/remote.rb
|
280
|
+
- lib/rspec-api/fixtures/empty.rb
|
281
|
+
- lib/rspec-api/fixtures/local.rb
|
282
|
+
- lib/rspec-api/fixtures/remote.rb
|
283
|
+
- lib/rspec-api/http_clients/empty.rb
|
284
|
+
- lib/rspec-api/http_clients/local.rb
|
285
|
+
- lib/rspec-api/http_clients/remote.rb
|
276
286
|
- lib/rspec-api/version.rb
|
287
|
+
- lib/rspec-api.rb
|
277
288
|
- MIT-LICENSE
|
278
289
|
- README.md
|
279
290
|
homepage: https://github.com/rspec-api/rspec-api
|
@@ -1,85 +0,0 @@
|
|
1
|
-
require 'active_support'
|
2
|
-
require 'rspec-api/matchers'
|
3
|
-
|
4
|
-
module DSL
|
5
|
-
module Request
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
module ClassMethods
|
9
|
-
# Creates an example group for expectations on the response body of the
|
10
|
-
# last API request and runs it to verify that it matches best practices:
|
11
|
-
# * if response is succesful and has a body
|
12
|
-
# - the body should be a JSON-marshalled Array or Hash
|
13
|
-
# - if request has a callback parameter, the body should be JSONP
|
14
|
-
# - if request has a sort parameter, the body should be sorted
|
15
|
-
# - if request has a filter parameter, the body should be filtered
|
16
|
-
# - if custom expectations are passed, they should pass
|
17
|
-
# - if some attributes are expected, the body should include them
|
18
|
-
def should_respond_with_expected_body(options = {})
|
19
|
-
context 'responds with a body that' do
|
20
|
-
it { should_be_valid_json options[:type] }
|
21
|
-
it { should_be_wrapped_by options[:callbacks] }
|
22
|
-
it { should_be_sorted_by options[:sorts] }
|
23
|
-
it { should_be_filtered_by options[:filters] }
|
24
|
-
it { should_have_attributes options[:attributes] }
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def should_be_valid_json(type)
|
30
|
-
expect(response).to be_valid_json_if response_is_successful?, type
|
31
|
-
end
|
32
|
-
|
33
|
-
# If the request had a 'callback' query parameter, then the body should be
|
34
|
-
# JSONP, otherwise it should not. For instance if the request was
|
35
|
-
# `GET /?method=alert` and the request `accepts_callback :method`, then
|
36
|
-
# the body must be a JSON wrapped in the alert(...) callback
|
37
|
-
# The +callback+ param says how the request might have been made, e.g.
|
38
|
-
# name: 'method', value: 'alert'... however to make sure that it was
|
39
|
-
# really made, we need to check that request_params['method'] is present
|
40
|
-
# and that is actually 'alert'
|
41
|
-
def should_be_wrapped_by(callback_params_sets)
|
42
|
-
callback_params = response_is_successful? && get_request_param_for_list(callback_params_sets)
|
43
|
-
value = callback_params[:value] if callback_params
|
44
|
-
expect(response).to be_a_jsonp_if callback_params, value
|
45
|
-
end
|
46
|
-
|
47
|
-
def should_be_sorted_by(sort_params_sets)
|
48
|
-
sort_params = response_is_successful? && get_request_param_for_list(sort_params_sets)
|
49
|
-
options = sort_params ? sort_params.slice(:by, :verse) : {}
|
50
|
-
expect(response).to be_sorted_if sort_params, options
|
51
|
-
end
|
52
|
-
|
53
|
-
def should_be_filtered_by(filter_params_sets)
|
54
|
-
# TODO: The following is just so the condition does not match if it's nil
|
55
|
-
# but this should be fixed in get_request_param_for_list
|
56
|
-
if filter_params_sets
|
57
|
-
filter_params_sets = filter_params_sets.dup
|
58
|
-
filter_params_sets.each{|x| x[:value] = request_params.fetch(x[:name].to_s, :something_nil)}
|
59
|
-
end
|
60
|
-
filter_params = response_is_successful? && get_request_param_for_list(filter_params_sets)
|
61
|
-
value = filter_params[:value] if filter_params
|
62
|
-
options = filter_params ? filter_params.slice(:by, :comparing_with) : {}
|
63
|
-
expect(response).to be_filtered_if filter_params, value, options
|
64
|
-
end
|
65
|
-
|
66
|
-
def should_have_attributes(attributes)
|
67
|
-
expect(response).to have_attributes_if response_is_successful?, attributes
|
68
|
-
end
|
69
|
-
|
70
|
-
def get_request_param_for_list(params_sets)
|
71
|
-
(params_sets || []).find do |params|
|
72
|
-
conditions = []
|
73
|
-
conditions << (request_params[params[:name].to_s] == params[:value])
|
74
|
-
params.fetch(:extra_fields, {}).each do |name, value|
|
75
|
-
conditions << (request_params[name.to_s] == value)
|
76
|
-
end
|
77
|
-
conditions.all?
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def response_is_successful?
|
82
|
-
response.status < 400 && !Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(response.status)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
require 'active_support'
|
2
|
-
require 'rack/utils'
|
3
|
-
require 'rspec-api/matchers'
|
4
|
-
|
5
|
-
module DSL
|
6
|
-
module Request
|
7
|
-
extend ActiveSupport::Concern
|
8
|
-
|
9
|
-
module ClassMethods
|
10
|
-
# Creates an example group for expectations on the response headers of
|
11
|
-
# last API request and runs it to verify that it matches best practices:
|
12
|
-
# * if request has entity body, the Content-Type header should be JSON
|
13
|
-
# * if request has pages, the Link header should have a 'rel=prev' link
|
14
|
-
def should_respond_with_expected_headers(options = {})
|
15
|
-
context 'responds with headers that' do
|
16
|
-
it { should_include_content_type :json }
|
17
|
-
it { should_have_prev_page_link options[:page] }
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def should_include_content_type(type)
|
25
|
-
expect(response).to include_content_type_if response_has_body?, type
|
26
|
-
end
|
27
|
-
|
28
|
-
def should_have_prev_page_link(page)
|
29
|
-
expect(response).to have_prev_page_link_if request_is_paginated?(page)
|
30
|
-
end
|
31
|
-
|
32
|
-
def response_has_body?
|
33
|
-
!Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(response.status)
|
34
|
-
end
|
35
|
-
|
36
|
-
def request_is_paginated?(page_parameter)
|
37
|
-
request_params.key? page_parameter.to_s
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
require 'active_support'
|
2
|
-
|
3
|
-
module DSL
|
4
|
-
module Request
|
5
|
-
extend ::ActiveSupport::Concern
|
6
|
-
|
7
|
-
module ClassMethods
|
8
|
-
# Runs a set of expectations on the result of the last API request.
|
9
|
-
# The most basic way to call `respond_with` is with a status code:
|
10
|
-
#
|
11
|
-
# respond_with :ok
|
12
|
-
#
|
13
|
-
# This simple line will run a number of expectations, based on best
|
14
|
-
# practices that any RESTful API is expected to match:
|
15
|
-
# * the returned HTTP status will be matched against 200 OK
|
16
|
-
# * the response headers will be checked for Content-Type etc.
|
17
|
-
# * the respone body will be checked for attributes etc.
|
18
|
-
#
|
19
|
-
# Additionally, the user can specify custom expectations for the
|
20
|
-
# response by passing a block to the method:
|
21
|
-
#
|
22
|
-
# respond_with :ok do |response|
|
23
|
-
# expect(response).to be_successful?
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# In this case, after all the *implicit* expectations are run, the
|
27
|
-
# JSON-parsed response body is passed to the block to make sure that
|
28
|
-
# (in the example above), the body is a hash with a 'color' key and
|
29
|
-
# the 'green' value
|
30
|
-
def respond_with(status_symbol, &block)
|
31
|
-
should_respond_with_status status_symbol
|
32
|
-
should_respond_with_expected_headers headers_options
|
33
|
-
should_respond_with_expected_body body_options
|
34
|
-
should_match_custom_response_expectations &block if block_given?
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def headers_options
|
40
|
-
{page: rspec_api.fetch(:page, {})[:name].to_s}
|
41
|
-
end
|
42
|
-
|
43
|
-
def body_options
|
44
|
-
{
|
45
|
-
type: rspec_api[:array] ? Array : Hash,
|
46
|
-
callbacks: rspec_api.fetch(:callbacks, []),
|
47
|
-
sorts: rspec_api.fetch(:sorts, []),
|
48
|
-
filters: rspec_api.fetch(:filters, []),
|
49
|
-
attributes: rspec_api.fetch(:attributes, {})
|
50
|
-
}
|
51
|
-
end
|
52
|
-
|
53
|
-
def should_match_custom_response_expectations(&block)
|
54
|
-
it { instance_exec response, @url_params, &block }
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def response
|
59
|
-
# To be overriden by more specific modules
|
60
|
-
OpenStruct.new # body: nil, status: nil, headers: {}
|
61
|
-
end
|
62
|
-
|
63
|
-
def response_body
|
64
|
-
JSON response_body_without_callbacks
|
65
|
-
rescue JSON::ParserError, JSON::GeneratorError
|
66
|
-
nil
|
67
|
-
end
|
68
|
-
|
69
|
-
def response_headers
|
70
|
-
response.headers || {}
|
71
|
-
end
|
72
|
-
|
73
|
-
def response_status
|
74
|
-
response.status
|
75
|
-
end
|
76
|
-
|
77
|
-
private
|
78
|
-
|
79
|
-
def response_body_without_callbacks
|
80
|
-
body = response.body
|
81
|
-
# TODO: extract the 'a_callback' constant
|
82
|
-
callback_pattern = %r[a_callback\((.*?)\)]
|
83
|
-
body =~ callback_pattern ? body.match(callback_pattern)[1] : body
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'active_support'
|
2
|
-
require 'rspec-api/matchers'
|
3
|
-
|
4
|
-
module DSL
|
5
|
-
module Request
|
6
|
-
extend ::ActiveSupport::Concern
|
7
|
-
|
8
|
-
module ClassMethods
|
9
|
-
# Creates an example group for expectations on the HTTP status code of the
|
10
|
-
# last API request and runs it to verify that it matches +status+.
|
11
|
-
def should_respond_with_status(status)
|
12
|
-
context 'responds with a status code that' do
|
13
|
-
it { expect(response).to have_status status }
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
require 'active_support'
|
2
|
-
module DSL
|
3
|
-
module Resource
|
4
|
-
extend ::ActiveSupport::Concern
|
5
|
-
|
6
|
-
module ClassMethods
|
7
|
-
def rspec_api
|
8
|
-
metadata[:rspec_api]
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.define_action(verb)
|
12
|
-
define_method verb do |route, args = {}, &block|
|
13
|
-
rspec_api.merge! array: args.delete(:array), verb: verb, route: route
|
14
|
-
args.merge! rspec_api_dsl: :route
|
15
|
-
describe("#{verb.upcase} #{route}", args, &block)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
define_action :get
|
20
|
-
define_action :put
|
21
|
-
define_action :patch
|
22
|
-
define_action :post
|
23
|
-
define_action :delete
|
24
|
-
|
25
|
-
|
26
|
-
def has_attribute(name, options = {}, &block)
|
27
|
-
if block_given?
|
28
|
-
# options[:type] can be symbol, hash or array
|
29
|
-
# but if you have a block we must make it a hash
|
30
|
-
options[:type] = Hash[*Array.wrap(options[:type]).map{|x| x.is_a?(Hash) ? [x.keys.first, x.values.first] : [x, {}]}.flatten] unless options[:type].is_a? Hash
|
31
|
-
# we only set the block as the new format of Object and Array
|
32
|
-
nest_attributes(options[:type], &Proc.new)
|
33
|
-
end
|
34
|
-
if @attribute_ancestors.present?
|
35
|
-
hash = @attribute_ancestors.last
|
36
|
-
hash.slice(:object, :array).each do |type, _|
|
37
|
-
(hash[type] ||= {})[name] = options
|
38
|
-
end
|
39
|
-
else
|
40
|
-
hash = (rspec_api[:attributes] ||= {})
|
41
|
-
hash[name] = options
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def nest_attributes(hash, &block)
|
46
|
-
(@attribute_ancestors ||= []).push hash
|
47
|
-
yield
|
48
|
-
@attribute_ancestors.pop
|
49
|
-
end
|
50
|
-
|
51
|
-
def accepts_page(page_parameter)
|
52
|
-
rspec_api[:page] = {name: page_parameter, value: 2}
|
53
|
-
end
|
54
|
-
|
55
|
-
def accepts_sort(sort_parameter, options={})
|
56
|
-
(rspec_api[:sorts] ||= []) << options.merge(name: 'sort', value: sort_parameter)
|
57
|
-
end
|
58
|
-
|
59
|
-
def accepts_filter(filter_parameter, options={})
|
60
|
-
(rspec_api[:filters] ||= []) << options.merge(name: filter_parameter)
|
61
|
-
end
|
62
|
-
|
63
|
-
def accepts_callback(callback_parameter)
|
64
|
-
(rspec_api[:callbacks] ||= []) << {name: callback_parameter.to_s, value: 'a_callback'}
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
data/lib/rspec-api/dsl/route.rb
DELETED
@@ -1,135 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/object' # present?
|
2
|
-
|
3
|
-
|
4
|
-
module DSL
|
5
|
-
module Route
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
def send_request(verb, route, body)
|
9
|
-
# To be overriden by more specific modules
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
def request(*args, &block)
|
14
|
-
text, values = parse_request_arguments args
|
15
|
-
sets_of_parameters.each do |params|
|
16
|
-
request_with_params text, values.merge(params), &block
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def setup_fixtures
|
21
|
-
# To be overriden by more specific modules
|
22
|
-
end
|
23
|
-
|
24
|
-
def existing(field)
|
25
|
-
# To be overriden by more specific modules
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def request_with_params(text, values = {}, &block)
|
31
|
-
context request_description(text, values), rspec_api_dsl: :request do
|
32
|
-
# NOTE: Having setup_fixtures inside the context sets up different
|
33
|
-
# fixtures for each `request` inside the same `get`. This might be
|
34
|
-
# a little slower on the DB, but ensures that two `request`s do not
|
35
|
-
# conflict. For instance, if you have two `request` inside a `delete`
|
36
|
-
# and the first deletes an instance, the second `request` is no
|
37
|
-
# affected.
|
38
|
-
setup_fixtures
|
39
|
-
setup_request rspec_api[:verb], rspec_api[:route], values
|
40
|
-
instance_eval(&block) if block_given?
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def sets_of_parameters
|
45
|
-
[].tap do |sets_of_params|
|
46
|
-
sets_of_params.push no_params
|
47
|
-
if rspec_api[:callbacks]
|
48
|
-
rspec_api[:callbacks].each do |callback|
|
49
|
-
sets_of_params.push callback_params(callback)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
if rspec_api[:array]
|
53
|
-
if rspec_api[:sorts]
|
54
|
-
rspec_api[:sorts].each do |sort|
|
55
|
-
sets_of_params.push sort_params(sort)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
if rspec_api[:filters]
|
59
|
-
rspec_api[:filters].each do |filter|
|
60
|
-
sets_of_params.push filter_params(filter)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
if rspec_api[:page]
|
64
|
-
sets_of_params.push page_params
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def no_params
|
71
|
-
{} # always send the original request without extra parameters
|
72
|
-
end
|
73
|
-
|
74
|
-
def sort_params(sort)
|
75
|
-
{}.tap do |params|
|
76
|
-
params[sort[:name]] = sort[:value]
|
77
|
-
sort.fetch(:extra_fields, {}).each do |name, value|
|
78
|
-
params[name] = value
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def page_params
|
84
|
-
{}.tap do |params|
|
85
|
-
params[rspec_api[:page][:name]] = rspec_api[:page][:value]
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def filter_params(filter)
|
90
|
-
{}.tap do |params|
|
91
|
-
params[filter[:name]] = existing filter[:by]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def callback_params(callback)
|
96
|
-
{}.tap do |params|
|
97
|
-
params[callback[:name]] = callback[:value]
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def setup_request(verb, route, values)
|
102
|
-
request = Proc.new {
|
103
|
-
interpolated_route, body = route.dup, values.dup
|
104
|
-
body.keys.each do |key|
|
105
|
-
if interpolated_route[":#{key}"]
|
106
|
-
value = body.delete(key)
|
107
|
-
value = value.call if value.is_a?(Proc)
|
108
|
-
interpolated_route[":#{key}"] = value.to_s
|
109
|
-
(@url_params ||= {})[key] = value
|
110
|
-
else
|
111
|
-
body[key] = body[key].call if body[key].is_a?(Proc)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
[interpolated_route, body]
|
115
|
-
}
|
116
|
-
before(:all) { send_request verb, *instance_eval(&request) }
|
117
|
-
end
|
118
|
-
|
119
|
-
def request_description(text, values)
|
120
|
-
if values.empty?
|
121
|
-
'by default'
|
122
|
-
else
|
123
|
-
text = "with" unless text.present?
|
124
|
-
"#{text} #{values.map{|k,v| "#{k}#{" #{v}" unless v.is_a?(Proc)}"}.to_sentence}"
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def parse_request_arguments(args)
|
129
|
-
text = args.first.is_a?(String) ? args[0] : ''
|
130
|
-
values = args.first.is_a?(String) ? args[1] : args[0]
|
131
|
-
[text, values || {}] # NOTE: In Ruby 2.0 we could write values.to_h
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
data/lib/rspec-api/http/local.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
require 'rack/test'
|
2
|
-
require 'rspec-api/http/local/route'
|
3
|
-
require 'rspec-api/http/local/request'
|
4
|
-
|
5
|
-
def app
|
6
|
-
Rails.application
|
7
|
-
end
|
8
|
-
|
9
|
-
RSpec.configuration.include Rack::Test::Methods, rspec_api_dsl: :route
|
10
|
-
RSpec.configuration.include Http::Local::Route, rspec_api_dsl: :route
|
11
|
-
RSpec.configuration.include Http::Local::Request, rspec_api_dsl: :request
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'faraday'
|
2
|
-
require 'faraday_middleware' # TODO: use autoload, we only need EncodeJson
|
3
|
-
require 'faraday-http-cache'
|
4
|
-
|
5
|
-
# faraday-http-cache is a great gem that correctly ignores Private Cache
|
6
|
-
# For the sake of saving Github calls, let's cache Private as well!
|
7
|
-
module Faraday
|
8
|
-
class HttpCache
|
9
|
-
class CacheControl
|
10
|
-
def private?
|
11
|
-
false
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
require 'rspec-api/http/remote/resource'
|
18
|
-
require 'rspec-api/http/remote/route'
|
19
|
-
require 'rspec-api/http/remote/request'
|
20
|
-
|
21
|
-
RSpec.configuration.include Http::Remote::Resource, rspec_api_dsl: :resource
|
22
|
-
RSpec.configuration.include Http::Remote::Request, rspec_api_dsl: :request
|
23
|
-
RSpec.configuration.include Http::Remote::Route, rspec_api_dsl: :route
|