rester 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/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:
|