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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: feecdb5b8bdfda29d9df2683370a79eb805365ef
4
- data.tar.gz: e56faba40a47774b17e4db017ec4b7b2fb09213a
3
+ metadata.gz: 00fb4dde16f074048bf41f0f245bfb9e7838fe57
4
+ data.tar.gz: 812ec217d03ff554627fd79713fd1e15cec8ee9a
5
5
  SHA512:
6
- metadata.gz: 32e24fa563229bcad341c0b06668c67e93fd96196124bcc74e23a1b9d4222765a82d95179d97ad7b9a7430a9c78af85660c66620c433b49ae55ad21220b61aeb
7
- data.tar.gz: 57982fbf4923f471ddaf64387d4de8b4ede4c1f12f8654ca3dbdc963fa6490cb0998e19fe173099c4cde289bb6c381a9635c7e36f6df04eda300157af1e6ff0f
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 = YAML.load_file(stub_filepath)
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, &block)
44
+ def with_context(context)
45
45
  @_context = context
46
- yield block
46
+ yield
47
47
  @_context = nil
48
48
  end
49
49
 
50
50
  private
51
51
 
52
52
  def _request(verb, path, params)
53
- response = _process_request(path, verb, params)
54
- [response['code'], response['body'].to_json]
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. Grab the response from the file and
76
- # reset the context
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 < Hash
3
+ class Response
4
4
  def initialize(status, hash={})
5
5
  @_status = status
6
- merge!(hash)
7
- _deep_freeze
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
- private
15
+ def to_h
16
+ @_data.dup
17
+ end
15
18
 
16
- def _deep_freeze(value=self)
17
- value.freeze
19
+ def ==(obj)
20
+ @_data == obj
21
+ end
22
+
23
+ private
18
24
 
19
- case value
20
- when Hash
21
- value.values.each { |v| _deep_freeze(v) }
22
- when Array
23
- value.each { |v| _deep_freeze(v) }
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 = YAML.load_file(@rester_stub_filepath)
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
- stub_params = @rester_stub[path][verb][context]['request']
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, stub_params)
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((raw_stub_response['body'] || {}).to_json,
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) { raw_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.dup.freeze
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 || Params.new).freeze
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
@@ -1,3 +1,3 @@
1
1
  module Rester
2
- VERSION = '0.3.3'
2
+ VERSION = '0.4.0'
3
3
  end
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.3.3
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-13 00:00:00.000000000 Z
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: