rester 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rester/client/adapters/stub_adapter.rb +7 -8
- data/lib/rester/client/response.rb +17 -11
- data/lib/rester/rspec.rb +6 -7
- data/lib/rester/service/resource/params.rb +2 -1
- data/lib/rester/service/resource.rb +2 -1
- data/lib/rester/utils/stub_file.rb +101 -0
- data/lib/rester/utils.rb +13 -0
- data/lib/rester/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00fb4dde16f074048bf41f0f245bfb9e7838fe57
|
4
|
+
data.tar.gz: 812ec217d03ff554627fd79713fd1e15cec8ee9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3753b97185a0000bcfc4368564873ff452c8ff989bd6f59d7a7959408b0346d3cbc4c61e6c6812ae138aefb63cf17f31be81ab8ee129a568bce1b51629609645
|
7
|
+
data.tar.gz: 2a24cbc7e691e0c64a93a6d35b97a94945614b6bf43284c28b126c9afbdfde34dc211dbd42f78f0288e2f8e2b62da8b96333224eb67b8c09ebb9767c46c9ee31
|
@@ -18,7 +18,7 @@ module Rester
|
|
18
18
|
end # Class Methods
|
19
19
|
|
20
20
|
def connect(stub_filepath, opts={})
|
21
|
-
@stub =
|
21
|
+
@stub = Utils::StubFile.new(stub_filepath)
|
22
22
|
end
|
23
23
|
|
24
24
|
def connected?
|
@@ -41,17 +41,17 @@ module Rester
|
|
41
41
|
_request('DELETE', path, params)
|
42
42
|
end
|
43
43
|
|
44
|
-
def with_context(context
|
44
|
+
def with_context(context)
|
45
45
|
@_context = context
|
46
|
-
yield
|
46
|
+
yield
|
47
47
|
@_context = nil
|
48
48
|
end
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
52
|
def _request(verb, path, params)
|
53
|
-
|
54
|
-
[
|
53
|
+
spec = _process_request(path, verb, params)
|
54
|
+
[spec['response_code'], spec['response'].to_json]
|
55
55
|
end
|
56
56
|
|
57
57
|
def _process_request(path, verb, params)
|
@@ -72,9 +72,8 @@ module Rester
|
|
72
72
|
end
|
73
73
|
|
74
74
|
# At this point, the 'request' is valid by matching a corresponding
|
75
|
-
# request in the stub yaml file.
|
76
|
-
|
77
|
-
stub[path][verb][context]['response']
|
75
|
+
# request in the stub yaml file.
|
76
|
+
stub[path][verb][context]
|
78
77
|
end
|
79
78
|
|
80
79
|
##
|
@@ -1,26 +1,32 @@
|
|
1
1
|
module Rester
|
2
2
|
class Client
|
3
|
-
class Response
|
3
|
+
class Response
|
4
4
|
def initialize(status, hash={})
|
5
5
|
@_status = status
|
6
|
-
|
7
|
-
|
6
|
+
@_data = hash.dup || {}
|
7
|
+
Utils.deep_freeze(@_data)
|
8
|
+
freeze
|
8
9
|
end
|
9
10
|
|
10
11
|
def successful?
|
11
12
|
@_status && @_status.between?(200, 299)
|
12
13
|
end
|
13
14
|
|
14
|
-
|
15
|
+
def to_h
|
16
|
+
@_data.dup
|
17
|
+
end
|
15
18
|
|
16
|
-
def
|
17
|
-
|
19
|
+
def ==(obj)
|
20
|
+
@_data == obj
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
18
24
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
25
|
+
def method_missing(meth, *args, &block)
|
26
|
+
if @_data.respond_to?(meth)
|
27
|
+
@_data.public_send(meth, *args, &block)
|
28
|
+
else
|
29
|
+
super
|
24
30
|
end
|
25
31
|
end
|
26
32
|
end # Response
|
data/lib/rester/rspec.rb
CHANGED
@@ -4,12 +4,13 @@ RSpec.configure do |config|
|
|
4
4
|
config.before :all, rester: // do |ex|
|
5
5
|
# Load the stub file
|
6
6
|
@rester_stub_filepath = ex.class.metadata[:rester]
|
7
|
-
@rester_stub =
|
7
|
+
@rester_stub = Rester::Utils::StubFile.new(@rester_stub_filepath)
|
8
8
|
|
9
9
|
# Hook up the LocalAdapter with the Service being tested
|
10
10
|
unless (klass = ex.class.described_class) < Rester::Service
|
11
11
|
raise "invalid service to test"
|
12
12
|
end
|
13
|
+
|
13
14
|
@rester_adapter = Rester::Client::Adapters::LocalAdapter.new(klass, {})
|
14
15
|
|
15
16
|
_validate_test_coverage(ex)
|
@@ -35,8 +36,7 @@ RSpec.configure do |config|
|
|
35
36
|
}.compact
|
36
37
|
|
37
38
|
begin
|
38
|
-
|
39
|
-
raw_stub_response = @rester_stub[path][verb][context]['response']
|
39
|
+
spec = @rester_stub[path][verb][context]
|
40
40
|
rescue NoMethodError
|
41
41
|
fail Rester::Errors::StubError,
|
42
42
|
"Could not find path: #{path.inspect} verb: #{verb.inspect} context: "\
|
@@ -47,7 +47,7 @@ RSpec.configure do |config|
|
|
47
47
|
# Raw response from the service.
|
48
48
|
# [HTTP CODE, JSON String]
|
49
49
|
ex.example_group.let(:raw_service_response) {
|
50
|
-
@rester_adapter.request(verb.downcase.to_sym, path,
|
50
|
+
@rester_adapter.request(verb.downcase.to_sym, path, spec['request'])
|
51
51
|
}
|
52
52
|
|
53
53
|
##
|
@@ -63,13 +63,12 @@ RSpec.configure do |config|
|
|
63
63
|
##
|
64
64
|
# Expected response body specified in by the stub.
|
65
65
|
ex.example_group.let(:stub_response) {
|
66
|
-
JSON.parse((
|
67
|
-
symbolize_names: true)
|
66
|
+
JSON.parse((spec['response'] || {}).to_json, symbolize_names: true)
|
68
67
|
}
|
69
68
|
|
70
69
|
##
|
71
70
|
# HTTP status code expected by the stub.
|
72
|
-
ex.example_group.let(:stub_response_code) {
|
71
|
+
ex.example_group.let(:stub_response_code) { spec['response_code'] }
|
73
72
|
|
74
73
|
##
|
75
74
|
# Set the subject to be the service response (parsed ruby hash of the
|
@@ -1,12 +1,13 @@
|
|
1
1
|
module Rester
|
2
2
|
class Service::Resource
|
3
3
|
class Params
|
4
|
+
DEFAULT_OPTS = { strict: true }.freeze
|
4
5
|
BASIC_TYPES = [String, Symbol, Float, Integer].freeze
|
5
6
|
|
6
7
|
attr_reader :options
|
7
8
|
|
8
9
|
def initialize(opts={}, &block)
|
9
|
-
@options = opts.
|
10
|
+
@options = DEFAULT_OPTS.merge(opts).freeze
|
10
11
|
@_required_fields = []
|
11
12
|
@_defaults = {}
|
12
13
|
@_all_fields = []
|
@@ -64,7 +64,8 @@ module Rester
|
|
64
64
|
|
65
65
|
def method_added(method_name)
|
66
66
|
if RESOURCE_METHODS.include?(method_name.to_sym)
|
67
|
-
method_params[method_name.to_sym] = (@_next_params ||
|
67
|
+
method_params[method_name.to_sym] = (@_next_params ||
|
68
|
+
Params.new(strict: false)).freeze
|
68
69
|
end
|
69
70
|
@_next_params = nil
|
70
71
|
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module Rester
|
2
|
+
module Utils
|
3
|
+
class StubFile
|
4
|
+
DEFAULT_TAGS = { 'successful' => 'true' }.freeze
|
5
|
+
|
6
|
+
attr_reader :path
|
7
|
+
|
8
|
+
def initialize(path)
|
9
|
+
@path = path
|
10
|
+
@_stub = StubFile.parse(path)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def method_missing(meth, *args, &block)
|
16
|
+
if @_stub.respond_to?(meth)
|
17
|
+
@_stub.public_send(meth, *args, &block)
|
18
|
+
else
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Class Methods
|
25
|
+
class << self
|
26
|
+
##
|
27
|
+
# Parses the stub file and returns the data as a hash
|
28
|
+
def parse(path)
|
29
|
+
parse!(YAML.load_file(path))
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Given a raw stub file hash, converts it to the format used internally.
|
34
|
+
def parse!(stub_hash)
|
35
|
+
stub_hash.each do |path, verbs|
|
36
|
+
next if ['version', 'consumer', 'producer'].include?(path)
|
37
|
+
|
38
|
+
verbs.each do |verb, contexts|
|
39
|
+
contexts.each do |context, spec|
|
40
|
+
_update_context(path, verb, context, spec)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Given a context hash, updates it for consumption by the rest of the
|
48
|
+
# StubAdapter (i.e., removes tags from "response" key and puts them in
|
49
|
+
# a "response_tags" key).
|
50
|
+
def _update_context(path, verb, context, spec)
|
51
|
+
responses = spec.select { |k,_|
|
52
|
+
k =~ /\Aresponse(\[(\w+) *= *(\w+)(, *(\w+) *= *(\w+))*\])?\z/
|
53
|
+
}
|
54
|
+
|
55
|
+
if responses.count == 0
|
56
|
+
fail Errors::StubError, "#{verb.upcase} #{path} is missing a " \
|
57
|
+
"response for the context #{context.inspect}"
|
58
|
+
elsif responses.count > 1
|
59
|
+
fail Errors::StubError, "#{verb.upcase} #{path} has too many " \
|
60
|
+
"responses defined for the context #{context.inspect}"
|
61
|
+
end
|
62
|
+
|
63
|
+
response_key = responses.keys.first
|
64
|
+
|
65
|
+
tags = _parse_tags(path, verb, context, response_key)
|
66
|
+
|
67
|
+
spec.merge!(
|
68
|
+
'response' => spec.delete(response_key),
|
69
|
+
'response_tags' => tags,
|
70
|
+
'response_code' => _parse_response_code(verb, tags)
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Takes a response key (e.g., "response[successful=false]") and parses out
|
76
|
+
# the tags (e.g., {"successful" => false})
|
77
|
+
def _parse_tags(path, verb, context, resp_key)
|
78
|
+
DEFAULT_TAGS.merge(resp_key.scan(/(\w+) *= *(\w+)/).to_h).tap { |tags|
|
79
|
+
_validate_tags(path, verb, context, tags)
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def _validate_tags(path, verb, context, tags)
|
84
|
+
unless ['true', 'false'].include?(tags['successful'])
|
85
|
+
fail Errors::StubError, '"successful" tag should be either "true" '\
|
86
|
+
'or "false" in' "#{verb.upcase} #{path} in context " \
|
87
|
+
"#{context.inspect}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def _parse_response_code(verb, tags)
|
92
|
+
if tags['successful'] == 'true'
|
93
|
+
(verb == 'POST') ? 201 : 200
|
94
|
+
else
|
95
|
+
400
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end # Class Methods
|
99
|
+
end # StubFile
|
100
|
+
end # Utils
|
101
|
+
end # Rester
|
data/lib/rester/utils.rb
CHANGED
@@ -2,6 +2,8 @@ require 'date'
|
|
2
2
|
|
3
3
|
module Rester
|
4
4
|
module Utils
|
5
|
+
autoload(:StubFile, 'rester/utils/stub_file')
|
6
|
+
|
5
7
|
class << self
|
6
8
|
##
|
7
9
|
# Determines the HTTP method/verb based on the method name.
|
@@ -65,6 +67,17 @@ module Rester
|
|
65
67
|
def underscore(str)
|
66
68
|
str.scan(/[A-Z][a-z]*/).map(&:downcase).join('_')
|
67
69
|
end
|
70
|
+
|
71
|
+
def deep_freeze(value)
|
72
|
+
value.freeze
|
73
|
+
|
74
|
+
case value
|
75
|
+
when Hash
|
76
|
+
value.values.each { |v| deep_freeze(v) }
|
77
|
+
when Array
|
78
|
+
value.each { |v| deep_freeze(v) }
|
79
|
+
end
|
80
|
+
end
|
68
81
|
end # Class methods
|
69
82
|
end # Utils
|
70
83
|
end # Rester
|
data/lib/rester/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rester
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Honer
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-11-
|
12
|
+
date: 2015-11-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -145,6 +145,7 @@ files:
|
|
145
145
|
- lib/rester/service/resource.rb
|
146
146
|
- lib/rester/service/resource/params.rb
|
147
147
|
- lib/rester/utils.rb
|
148
|
+
- lib/rester/utils/stub_file.rb
|
148
149
|
- lib/rester/version.rb
|
149
150
|
homepage: http://github.com/payout/rester
|
150
151
|
licenses:
|