rspec-api 0.5.0 → 0.7.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/README.md +1 -0
- data/lib/rspec-api.rb +1 -1
- data/lib/rspec-api/resource.rb +50 -0
- data/lib/rspec-api/resource/accepts.rb +70 -0
- data/lib/rspec-api/resource/actions.rb +40 -0
- data/lib/rspec-api/resource/has_attribute.rb +29 -0
- data/lib/rspec-api/resource/options.rb +27 -0
- data/lib/rspec-api/version.rb +1 -1
- metadata +27 -20
- data/lib/rspec-api/dsl.rb +0 -45
- data/lib/rspec-api/dsl/accepts.rb +0 -46
- data/lib/rspec-api/dsl/actions.rb +0 -36
- data/lib/rspec-api/dsl/attributes.rb +0 -13
- data/lib/rspec-api/dsl/requests.rb +0 -78
- data/lib/rspec-api/dsl/responses.rb +0 -37
- data/lib/rspec-api/fixtures/empty.rb +0 -35
- data/lib/rspec-api/fixtures/local.rb +0 -50
- data/lib/rspec-api/fixtures/remote.rb +0 -82
- data/lib/rspec-api/http_clients/empty.rb +0 -14
- data/lib/rspec-api/http_clients/local.rb +0 -28
- data/lib/rspec-api/http_clients/remote.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5d13d986f0266551e0dc9cb65d55825b7963cbd
|
4
|
+
data.tar.gz: 5020ab2bc422a5c256b9008e2028209f10f7637a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7db05e3f65bbd82848de2ee0fbfa62be001f535c1e52857ff003baaa91e4d4808f5801898de4539cdba97ef7384b6883aaf3a62e00d477fad7eeead28943ebb9
|
7
|
+
data.tar.gz: 8ed56a2947fd64ec56b1f47795a6d057d1e54ab1f5e66236faa3b87eab736bf67a7c469c63eaa8dc16655f023b774d20d6e61f145ae894799574557cc3499f48
|
data/README.md
CHANGED
data/lib/rspec-api.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require 'rspec-api/
|
1
|
+
require 'rspec-api/resource'
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rspec/core'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
require 'rspec-api/resource/actions'
|
4
|
+
require 'rspec-api/resource/options'
|
5
|
+
require 'rspec-api/resource/has_attribute'
|
6
|
+
require 'rspec-api/resource/accepts'
|
7
|
+
|
8
|
+
module RSpecApi
|
9
|
+
# Provides actions and expectations method to RSpec Example groups, useful to
|
10
|
+
# describe the endpoints and expectations of a web API resource.
|
11
|
+
#
|
12
|
+
# To have these matchers available inside of an RSpec `describe` block,
|
13
|
+
# include that block inside a block with the `:rspec_api` metadata, or
|
14
|
+
# explicitly include the RSpecApi::Resource module.
|
15
|
+
#
|
16
|
+
# @example Tag a `describe` block as `:rspec_api`:
|
17
|
+
# describe "Artists", rspec_api: true do
|
18
|
+
# ... # here you can write `get`, `has_attribute`, `host`, etc.
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# @example Explicitly include the RSpecApi::Resource module
|
22
|
+
# describe "Artists" do
|
23
|
+
# include RSpecApi::Resource
|
24
|
+
# ... # here you can write `get`, `has_attribute`, `host`, etc.
|
25
|
+
# end
|
26
|
+
module Resource
|
27
|
+
include Actions
|
28
|
+
include Options
|
29
|
+
include HasAttribute
|
30
|
+
include Accepts
|
31
|
+
end
|
32
|
+
end
|
33
|
+
RSpec.configuration.extend RSpecApi::Resource, rspec_api: true
|
34
|
+
|
35
|
+
# You can also have the methods available in a RSpec Example group using
|
36
|
+
# `resource`. This is the only method that RSpecApi adds to the top-level
|
37
|
+
# namespace and it's equivalent to a `describe` block with RSpecApi::Resource:
|
38
|
+
#
|
39
|
+
# @example Describe the resource artist:
|
40
|
+
#
|
41
|
+
# resource :artist do
|
42
|
+
# ... # here you can write `get`, `has_attribute`, `host`, etc.
|
43
|
+
# end
|
44
|
+
def resource(name, args = {}, &block)
|
45
|
+
describe name.to_s.pluralize.humanize, args do
|
46
|
+
extend RSpecApi::Resource
|
47
|
+
rspec_api_resource[:resource_name] = name
|
48
|
+
instance_exec &block
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'rspec-api/resource/options'
|
2
|
+
|
3
|
+
module RSpecApi
|
4
|
+
module Resource
|
5
|
+
module Accepts
|
6
|
+
def accepts(options = {})
|
7
|
+
add_request_for accepts_sort(options) if options.key? :sort
|
8
|
+
add_request_for accepts_filter(options) if options.key? :filter
|
9
|
+
add_request_for accepts_page(options) if options.key? :page
|
10
|
+
add_request_for accepts_callback(options) if options.key? :callback
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def add_request_for(opts = {})
|
16
|
+
(rspec_api_resource[:extra_requests] ||= []) << opts
|
17
|
+
end
|
18
|
+
|
19
|
+
def accepts_sort(opts = {})
|
20
|
+
{params: sort_params(opts), expect: sort_expect(opts)}
|
21
|
+
end
|
22
|
+
|
23
|
+
def sort_params(opts = {})
|
24
|
+
{sort: opts[:sort]}.merge(opts.fetch :sort_if, {})
|
25
|
+
end
|
26
|
+
|
27
|
+
def sort_expect(opts = {})
|
28
|
+
{sort: opts.slice(:by, :verse)}
|
29
|
+
end
|
30
|
+
|
31
|
+
def accepts_filter(opts = {})
|
32
|
+
{params: filter_params(opts), expect: filter_expect(opts)}
|
33
|
+
end
|
34
|
+
|
35
|
+
def filter_params(opts = {})
|
36
|
+
{}.tap{|params| params[opts[:filter]] = opts[:value]}
|
37
|
+
end
|
38
|
+
|
39
|
+
def filter_expect(opts = {})
|
40
|
+
{filter: opts.slice(:by, :compare_with, :value)}
|
41
|
+
end
|
42
|
+
|
43
|
+
def accepts_page(opts = {})
|
44
|
+
{params: page_params(opts), expect: page_expect(opts)}
|
45
|
+
end
|
46
|
+
|
47
|
+
def page_params(opts = {})
|
48
|
+
{}.tap{|params| params[opts[:page]] = 2}
|
49
|
+
end
|
50
|
+
|
51
|
+
def page_expect(opts = {})
|
52
|
+
{page_links: true}
|
53
|
+
end
|
54
|
+
|
55
|
+
def accepts_callback(opts = {})
|
56
|
+
# NOTE: This is the only accepts that affects *all* the requests,
|
57
|
+
# not just the ones that return a collection
|
58
|
+
{params: callback_params(opts), expect: callback_expect(opts), all: true}
|
59
|
+
end
|
60
|
+
|
61
|
+
def callback_params(opts = {})
|
62
|
+
{}.tap{|params| params[opts[:callback]] = 'anyCallback'}
|
63
|
+
end
|
64
|
+
|
65
|
+
def callback_expect(opts = {})
|
66
|
+
{callback: 'anyCallback'}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rspec-api/requests'
|
2
|
+
require 'rspec-api/resource/options'
|
3
|
+
|
4
|
+
module RSpecApi
|
5
|
+
module Resource
|
6
|
+
module Actions
|
7
|
+
[:get, :put, :patch, :post, :delete].each do |action|
|
8
|
+
define_method action do |route, rspec_api_options = {}, &block|
|
9
|
+
options = rspec_api_options.merge route: route, action: action
|
10
|
+
options = rspec_api_resource.merge options
|
11
|
+
describe description_for(options), rspec_api_params: options do
|
12
|
+
extend RSpecApi::Requests
|
13
|
+
instance_eval &block if block
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def description_for(params = {})
|
21
|
+
action, name, plural = params.values_at(:action, :resource_name, :collection)
|
22
|
+
[verb_for(action), object_for(name.to_s, plural)].compact.join ' '
|
23
|
+
end
|
24
|
+
|
25
|
+
def verb_for(action)
|
26
|
+
case action
|
27
|
+
when :get then 'Getting'
|
28
|
+
when :put then 'Editing'
|
29
|
+
when :patch then 'Editing'
|
30
|
+
when :post then 'Creating'
|
31
|
+
when :delete then 'Deleting'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def object_for(name, plural)
|
36
|
+
plural ? "a list of #{name.pluralize}" : "one #{name}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'active_support/core_ext/object/blank'
|
2
|
+
require 'rspec-api/resource/options'
|
3
|
+
|
4
|
+
module RSpecApi
|
5
|
+
module Resource
|
6
|
+
module HasAttribute
|
7
|
+
def has_attribute(name, options, &block)
|
8
|
+
if block_given?
|
9
|
+
options[:type] = Hash[options[:type], {}]
|
10
|
+
nest_attributes options[:type], &Proc.new
|
11
|
+
end
|
12
|
+
if @attribute_ancestors.present?
|
13
|
+
hash = @attribute_ancestors.last
|
14
|
+
hash.each{|type, _| (hash[type] ||= {})[name] = options}
|
15
|
+
else
|
16
|
+
(rspec_api_resource[:attributes] ||= {})[name] = options
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def nest_attributes(hash, &block)
|
23
|
+
(@attribute_ancestors ||= []).push hash
|
24
|
+
yield
|
25
|
+
@attribute_ancestors.pop
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module RSpecApi
|
2
|
+
module Resource
|
3
|
+
module Options
|
4
|
+
def adapter(*args)
|
5
|
+
rspec_api_resource[:adapter] = args
|
6
|
+
end
|
7
|
+
|
8
|
+
def host(host)
|
9
|
+
rspec_api_resource[:host] = host
|
10
|
+
end
|
11
|
+
|
12
|
+
def throttle(seconds_to_sleep)
|
13
|
+
rspec_api_resource[:throttle] = seconds_to_sleep
|
14
|
+
end
|
15
|
+
|
16
|
+
def authorize_with(auth_params = {})
|
17
|
+
rspec_api_resource[:authorize_with] = auth_params
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def rspec_api_resource
|
23
|
+
(metadata[:rspec_api_resource] ||= {})
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
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.7.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-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -25,33 +25,47 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: rspec-api-
|
28
|
+
name: rspec-api-requests
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
33
|
+
version: 0.7.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: 0.
|
40
|
+
version: 0.7.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec-api-expectations
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
47
|
+
version: 0.7.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
54
|
+
version: 0.7.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-api-matchers
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.7.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.7.0
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rack
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -87,7 +101,7 @@ dependencies:
|
|
87
101
|
- - '>='
|
88
102
|
- !ruby/object:Gem::Version
|
89
103
|
version: '0'
|
90
|
-
type: :
|
104
|
+
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
@@ -271,18 +285,11 @@ executables: []
|
|
271
285
|
extensions: []
|
272
286
|
extra_rdoc_files: []
|
273
287
|
files:
|
274
|
-
- lib/rspec-api/
|
275
|
-
- lib/rspec-api/
|
276
|
-
- lib/rspec-api/
|
277
|
-
- lib/rspec-api/
|
278
|
-
- lib/rspec-api/
|
279
|
-
- lib/rspec-api/dsl.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
|
288
|
+
- lib/rspec-api/resource/accepts.rb
|
289
|
+
- lib/rspec-api/resource/actions.rb
|
290
|
+
- lib/rspec-api/resource/has_attribute.rb
|
291
|
+
- lib/rspec-api/resource/options.rb
|
292
|
+
- lib/rspec-api/resource.rb
|
286
293
|
- lib/rspec-api/version.rb
|
287
294
|
- lib/rspec-api.rb
|
288
295
|
- MIT-LICENSE
|
data/lib/rspec-api/dsl.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'rspec-api/dsl/accepts'
|
2
|
-
require 'rspec-api/dsl/actions'
|
3
|
-
require 'rspec-api/dsl/attributes'
|
4
|
-
|
5
|
-
module RSpecApi
|
6
|
-
module DSL
|
7
|
-
include Accepts
|
8
|
-
include Actions
|
9
|
-
include Attributes
|
10
|
-
include Fixtures
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
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
|
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
|
45
|
-
end
|
@@ -1,46 +0,0 @@
|
|
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
|
-
|
@@ -1,36 +0,0 @@
|
|
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
|
@@ -1,13 +0,0 @@
|
|
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
|
@@ -1,78 +0,0 @@
|
|
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
|
@@ -1,37 +0,0 @@
|
|
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
|
@@ -1,35 +0,0 @@
|
|
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
|
@@ -1,50 +0,0 @@
|
|
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
|
@@ -1,82 +0,0 @@
|
|
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
|
@@ -1,14 +0,0 @@
|
|
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
|
@@ -1,28 +0,0 @@
|
|
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,40 +0,0 @@
|
|
1
|
-
require 'faraday'
|
2
|
-
require 'faraday_middleware' # TODO: use autoload, we only need EncodeJson
|
3
|
-
require 'faraday-http-cache'
|
4
|
-
require 'logger'
|
5
|
-
|
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)
|
16
|
-
logger = Logger.new 'log/faraday.log'
|
17
|
-
|
18
|
-
conn = Faraday.new 'https://api.github.com/' do |c| # TODO: Pass host as a parameter
|
19
|
-
# NOTE: The order is **important**! Leave HttpCache first
|
20
|
-
c.use Faraday::HttpCache, serializer: Marshal, store: :file_store, store_options: ['/tmp/faraday'], logger: logger
|
21
|
-
c.use FaradayMiddleware::EncodeJson # query params are not JSON(body) but data are
|
22
|
-
c.use Faraday::Response::Logger, logger
|
23
|
-
c.use Faraday::Adapter::NetHttp
|
24
|
-
end
|
25
|
-
|
26
|
-
conn.headers[:user_agent] = 'RSpec API'
|
27
|
-
conn.authorization *authorization.flatten
|
28
|
-
sleep 0.5 # TODO: Pass as a parameter
|
29
|
-
|
30
|
-
@last_response = conn.send verb, route, body do |request|
|
31
|
-
@last_request = request
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def last_response
|
36
|
-
@last_response
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|