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