rspec-api 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|