holoserve 0.4.1 → 0.4.2
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.
- data/README.rdoc +55 -45
- data/Rakefile +1 -1
- data/lib/holoserve/interface/control/index.rb +42 -0
- data/lib/holoserve/interface/control.rb +5 -0
- data/lib/holoserve/interface/event.rb +38 -0
- data/lib/holoserve/interface/fake.rb +33 -18
- data/lib/holoserve/interface.rb +16 -0
- data/lib/holoserve/pair/finder.rb +23 -1
- data/lib/holoserve/pair/loader.rb +30 -13
- data/lib/holoserve/pair/validator.rb +47 -0
- data/lib/holoserve/pair.rb +1 -0
- data/lib/holoserve/request/selector.rb +21 -0
- data/lib/holoserve/request.rb +1 -1
- data/lib/holoserve/response/combiner.rb +1 -1
- data/lib/holoserve/response/selector.rb +6 -13
- data/lib/holoserve/tool/hash/matcher.rb +53 -0
- data/lib/holoserve/tool/hash.rb +1 -0
- data/spec/lib/holoserve/pair/validator_spec.rb +52 -0
- data/spec/lib/holoserve/request/selector_spec.rb +69 -0
- data/spec/lib/holoserve/tool/hash/matcher_spec.rb +136 -0
- metadata +73 -18
- data/lib/holoserve/request/matcher.rb +0 -74
data/README.rdoc
CHANGED
@@ -98,11 +98,11 @@ Returns a list of all requests that has been received, but couldn't be handled.
|
|
98
98
|
|
99
99
|
=== GET /_control/history
|
100
100
|
|
101
|
-
Returns a list of
|
101
|
+
Returns a list of hashes, which include the names/id of pairs that has been triggered, with a request variant and a list of response variants.
|
102
102
|
|
103
103
|
==== Response example
|
104
104
|
|
105
|
-
[
|
105
|
+
[{"id":"test_request","request_variant":"default","response_variants":["default","alternative"]}]
|
106
106
|
|
107
107
|
=== DELETE /_control/history
|
108
108
|
|
@@ -112,9 +112,10 @@ Removes all entries from the history.
|
|
112
112
|
|
113
113
|
The request/response pair file should have the following format.
|
114
114
|
|
115
|
-
|
115
|
+
requests:
|
116
|
+
default:
|
116
117
|
imports:
|
117
|
-
- path: "
|
118
|
+
- path: "test_fixtures.users.0"
|
118
119
|
as: "parameters"
|
119
120
|
only: [ "username", "password" ]
|
120
121
|
method: "POST"
|
@@ -123,55 +124,64 @@ The request/response pair file should have the following format.
|
|
123
124
|
HTTP_USER_AGENT: "Ruby"
|
124
125
|
oauth:
|
125
126
|
oauth_token: "12345"
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
- path: "test_fixture.users.0"
|
132
|
-
as: "json.user"
|
133
|
-
transitions:
|
134
|
-
session_one: "existing"
|
135
|
-
"user_one == :missing":
|
136
|
-
json:
|
137
|
-
message: "user not found"
|
138
|
-
- request:
|
127
|
+
responses:
|
128
|
+
default:
|
129
|
+
status: 200
|
130
|
+
found:
|
131
|
+
condition: "username == :existing"
|
139
132
|
imports:
|
140
|
-
- path: "
|
141
|
-
as: "
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
oauth_token: "12345"
|
151
|
-
responses:
|
152
|
-
"user_one == :existing":
|
153
|
-
status: 401
|
154
|
-
json:
|
155
|
-
message: "invalid password"
|
156
|
-
"user_one == :missing":
|
157
|
-
status: 200
|
158
|
-
json:
|
159
|
-
message: "user not found"
|
160
|
-
|
161
|
-
The fixture data where this example pair definition relies on, could look like to following.
|
133
|
+
- path: "test_fixtures.users.0"
|
134
|
+
as: "json.user"
|
135
|
+
transitions:
|
136
|
+
session_one: "existing"
|
137
|
+
not_found:
|
138
|
+
condition: "username == :missing"
|
139
|
+
json:
|
140
|
+
message: "user not found"
|
141
|
+
|
142
|
+
The fixture data where this example pair definition relies on, could look like the following.
|
162
143
|
|
163
144
|
users:
|
164
145
|
- email: "one@test.com"
|
165
146
|
username: "one"
|
166
147
|
password: "valid"
|
167
148
|
|
168
|
-
This example defines
|
169
|
-
|
170
|
-
are posted and the second one reacts on the transmission of <tt>username=one</tt> and <tt>password=invalid</tt>.
|
149
|
+
This example defines a request/response pair situation. It uses <tt>username=one</tt> and <tt>password=valid</tt>
|
150
|
+
as parameters.
|
171
151
|
|
172
|
-
If the state includes <tt>user_one == :existing</tt>, the
|
173
|
-
as json
|
174
|
-
<tt>user_one == :missing</tt>, both requests would be replied with the message "user not found".
|
152
|
+
If the state includes <tt>condition: "user_one == :existing"</tt>, the response would return the complete user object encoded
|
153
|
+
as json. If the state includes <tt>user_one == :missing</tt>, the request would be replied with the message "user not found".
|
175
154
|
|
176
155
|
The <tt>transitions</tt> part of the response allows you set the successor state. If a response is selected, the
|
177
156
|
corresponding transitions will be evaluated.
|
157
|
+
|
158
|
+
|
159
|
+
requests:
|
160
|
+
default:
|
161
|
+
imports:
|
162
|
+
- path: "test_fixtures.users.0.email"
|
163
|
+
as: "parameters"
|
164
|
+
method: "POST"
|
165
|
+
path: "/valid_email"
|
166
|
+
responses:
|
167
|
+
default:
|
168
|
+
status: 200
|
169
|
+
found:
|
170
|
+
condition: "email == :existing"
|
171
|
+
imports:
|
172
|
+
- path: "test_fixtures.users.0.username"
|
173
|
+
as: "json.user.username"
|
174
|
+
transitions:
|
175
|
+
session_one: "existing"
|
176
|
+
not_found:
|
177
|
+
condition: "email == :missing"
|
178
|
+
json:
|
179
|
+
message: "email address not found"
|
180
|
+
|
181
|
+
This example relies on the same fixture file used above.
|
182
|
+
|
183
|
+
This time it uses <tt>email=one@test.com</tt> as a parameter.
|
184
|
+
If the state includes <tt>condition: "email == :existing"</tt>, the response would return a username of the email address
|
185
|
+
owner as json.
|
186
|
+
|
187
|
+
If the state includes <tt>email == :missing</tt>, the response would be a message "email address not found" in json.
|
data/Rakefile
CHANGED
@@ -5,4 +5,4 @@ load File.join(File.dirname(__FILE__), "tasks", "features.rake")
|
|
5
5
|
load File.join(File.dirname(__FILE__), "tasks", "gem.rake")
|
6
6
|
load File.join(File.dirname(__FILE__), "tasks", "goliath.rake")
|
7
7
|
load File.join(File.dirname(__FILE__), "tasks", "rdoc.rake")
|
8
|
-
load File.join(File.dirname(__FILE__), "tasks", "spec.rake")
|
8
|
+
load File.join(File.dirname(__FILE__), "tasks", "spec.rake")
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'goliath/api'
|
2
|
+
require 'goliath/rack/templates'
|
3
|
+
require 'slim'
|
4
|
+
require 'sass'
|
5
|
+
require 'coffee_script'
|
6
|
+
|
7
|
+
module Holoserve::Interface::Control::Index
|
8
|
+
|
9
|
+
class Fetch < Goliath::API
|
10
|
+
include Goliath::Rack::Templates
|
11
|
+
include Holoserve::Interface::Control::Helper
|
12
|
+
|
13
|
+
def response(environment)
|
14
|
+
case environment["REQUEST_URI"]
|
15
|
+
when "/_control"
|
16
|
+
render_slim :index
|
17
|
+
when "/_control/stylesheets/screen.css"
|
18
|
+
render_scss :screen
|
19
|
+
when "/_control/javascripts/all.js"
|
20
|
+
render_coffee :all
|
21
|
+
else
|
22
|
+
not_found
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def render_slim(template)
|
29
|
+
ok slim(template, :views => File.join(Holoserve::Interface::ROOT, "views")), "text/html"
|
30
|
+
end
|
31
|
+
|
32
|
+
def render_scss(template)
|
33
|
+
ok scss(template, :views => File.join(Holoserve::Interface::ROOT, "stylesheets")), "text/css"
|
34
|
+
end
|
35
|
+
|
36
|
+
def render_coffee(template)
|
37
|
+
ok coffee(template, :views => File.join(Holoserve::Interface::ROOT, "javascripts")), "text/javascript"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -4,6 +4,7 @@ module Holoserve::Interface::Control
|
|
4
4
|
|
5
5
|
autoload :Bucket, File.join(File.dirname(__FILE__), "control", "bucket")
|
6
6
|
autoload :History, File.join(File.dirname(__FILE__), "control", "history")
|
7
|
+
autoload :Index, File.join(File.dirname(__FILE__), "control", "index")
|
7
8
|
autoload :Pair, File.join(File.dirname(__FILE__), "control", "pair")
|
8
9
|
autoload :State, File.join(File.dirname(__FILE__), "control", "state")
|
9
10
|
|
@@ -25,6 +26,10 @@ module Holoserve::Interface::Control
|
|
25
26
|
[ 400, { }, [ "bad request" ] ]
|
26
27
|
end
|
27
28
|
|
29
|
+
def not_found
|
30
|
+
[ 404, { }, [ "not found" ] ]
|
31
|
+
end
|
32
|
+
|
28
33
|
def bucket
|
29
34
|
config[:bucket] ||= [ ]
|
30
35
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
class Holoserve::Interface::Event
|
4
|
+
|
5
|
+
def on_open(environment)
|
6
|
+
self.class.handler = environment["handler"]
|
7
|
+
end
|
8
|
+
|
9
|
+
def on_message(environment, message)
|
10
|
+
environment.logger.info "MESSAGE #{message}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_close(environment)
|
14
|
+
environment.logger.info("WS CLOSED")
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_error(environment, error)
|
18
|
+
environment.logger.error error
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.handler=(value)
|
22
|
+
@handler = value
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.send_pair_event(id)
|
26
|
+
send_message "pair:#{id}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.send_bucket_event(request)
|
30
|
+
send_message "bucket:#{JSON.dump(request)}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.send_message(text)
|
34
|
+
return unless @handler
|
35
|
+
@handler.send_text_frame text
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -3,43 +3,58 @@ require 'pp'
|
|
3
3
|
|
4
4
|
class Holoserve::Interface::Fake < Goliath::API
|
5
5
|
|
6
|
+
class NoResponseError < StandardError
|
7
|
+
|
8
|
+
attr_reader :id
|
9
|
+
attr_reader :request_variant
|
10
|
+
|
11
|
+
def initialize(id, request_variant)
|
12
|
+
@id, @request_variant = id, request_variant
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
6
17
|
use Goliath::Rack::Params
|
7
18
|
|
8
19
|
def response(env)
|
9
20
|
request = Holoserve::Request::Decomposer.new(env, params).hash
|
10
|
-
|
21
|
+
finder = Holoserve::Pair::Finder.new(pairs, request)
|
22
|
+
pair = finder.pair
|
11
23
|
if pair
|
12
|
-
id, responses =
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
24
|
+
id, request_variant, responses = finder.id, finder.variant, pair[:responses]
|
25
|
+
|
26
|
+
selector = Holoserve::Response::Selector.new responses, state.merge(:request_variant => request_variant), logger
|
27
|
+
response_variant = selector.selection
|
28
|
+
|
29
|
+
response = if response_variant == :default
|
30
|
+
responses[:default] || { }
|
31
|
+
elsif response_variant
|
32
|
+
Holoserve::Tool::Merger.new(responses[:default] || { }, responses[response_variant]).result
|
33
|
+
else
|
34
|
+
raise NoResponseError, id, request_variant
|
35
|
+
end
|
36
|
+
Holoserve::State::Updater.new(state, response[:transitions]).perform
|
37
|
+
history << {:id => id, :request_variant => request_variant, :response_variant => response_variant}
|
19
38
|
|
20
|
-
|
39
|
+
Holoserve::Interface::Event.send_pair_event id
|
40
|
+
logger.info "handled request [#{id}] with request variant [#{request_variant}] and response variant [#{response_variant}]"
|
21
41
|
|
22
|
-
response = Holoserve::Response::Combiner.new(default_response, selected_responses).response
|
23
42
|
Holoserve::Response::Composer.new(response).response_array
|
24
43
|
else
|
25
44
|
bucket << request
|
45
|
+
Holoserve::Interface::Event.send_bucket_event request
|
26
46
|
logger.error "received unhandled request\n" + request.pretty_inspect
|
27
47
|
|
28
48
|
not_found
|
29
49
|
end
|
50
|
+
rescue NoResponseError => error
|
51
|
+
logger.warn "could not select any response for request [#{error.id}] with request variant [#{error.request_variant}]"
|
30
52
|
end
|
31
53
|
|
32
54
|
private
|
33
55
|
|
34
|
-
def update_state(default_response, selected_responses)
|
35
|
-
Holoserve::State::Updater.new(state, default_response[:transitions]).perform
|
36
|
-
(selected_responses || [ ]).each do |response|
|
37
|
-
Holoserve::State::Updater.new(state, response[:transitions]).perform
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
56
|
def not_found
|
42
|
-
[ 404, { :"Content-Type" => "text/plain" }, [ "no response found for this request" ] ]
|
57
|
+
[ 404, { :"Content-Type" => "text/plain" }, [ "no response found for this request\n" ] ]
|
43
58
|
end
|
44
59
|
|
45
60
|
def bucket
|
data/lib/holoserve/interface.rb
CHANGED
@@ -3,8 +3,22 @@ require 'goliath/api'
|
|
3
3
|
class Holoserve::Interface < Goliath::API
|
4
4
|
|
5
5
|
autoload :Control, File.join(File.dirname(__FILE__), "interface", "control")
|
6
|
+
autoload :Event, File.join(File.dirname(__FILE__), "interface", "event")
|
6
7
|
autoload :Fake, File.join(File.dirname(__FILE__), "interface", "fake")
|
7
8
|
|
9
|
+
ROOT = File.expand_path(File.join(File.dirname(__FILE__), "..", "..")).freeze unless defined?(ROOT)
|
10
|
+
|
11
|
+
use Rack::Static,
|
12
|
+
:root => File.join(ROOT, "public"),
|
13
|
+
:urls => {
|
14
|
+
"/_control/favicon.ico" => "favicon.ico",
|
15
|
+
"/_control/javascripts/vendor/jquery-1.7.2.min.js" => "javascripts/vendor/jquery-1.7.2.min.js",
|
16
|
+
"/_control/javascripts/vendor/jquery.color.js" => "javascripts/vendor/jquery.color.js",
|
17
|
+
"/_control/javascripts/vendor/bootstrap-transition.js" => "javascripts/vendor/bootstrap-transition.js"
|
18
|
+
}
|
19
|
+
|
20
|
+
map "/_control/event", Event
|
21
|
+
|
8
22
|
get "/_control/bucket", Control::Bucket::Fetch
|
9
23
|
delete "/_control/bucket", Control::Bucket::Delete
|
10
24
|
|
@@ -18,6 +32,8 @@ class Holoserve::Interface < Goliath::API
|
|
18
32
|
get "/_control/state", Control::State::Fetch
|
19
33
|
delete "/_control/state", Control::State::Delete
|
20
34
|
|
35
|
+
get "/_control*", Control::Index::Fetch
|
36
|
+
|
21
37
|
map "/*", Fake
|
22
38
|
|
23
39
|
end
|
@@ -6,9 +6,31 @@ class Holoserve::Pair::Finder
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def pair
|
9
|
+
return @pair unless find_pair.nil?
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def id
|
14
|
+
return @id unless find_pair.nil?
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def variant
|
19
|
+
return @variant unless find_pair.nil?
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def find_pair
|
9
26
|
return nil unless @pairs
|
10
27
|
@pairs.each do |id, pair|
|
11
|
-
|
28
|
+
@variant = Holoserve::Request::Selector.new(@request, pair[:requests]).selection
|
29
|
+
unless @variant.nil?
|
30
|
+
@pair = pair
|
31
|
+
@id = id
|
32
|
+
return ""
|
33
|
+
end
|
12
34
|
end
|
13
35
|
nil
|
14
36
|
end
|
@@ -7,6 +7,9 @@ class Holoserve::Pair::Loader
|
|
7
7
|
@fixtures, @pairs = { }, { }
|
8
8
|
@fixture_file_pattern, @pair_file_pattern = fixture_file_pattern, pair_file_pattern
|
9
9
|
@logger = logger
|
10
|
+
@validator = Holoserve::Pair::Validator.new
|
11
|
+
rescue Holoserve::Pair::Validator::InvalidSchemaError => error
|
12
|
+
@logger.error error.inspect
|
10
13
|
end
|
11
14
|
|
12
15
|
def pairs
|
@@ -21,22 +24,33 @@ class Holoserve::Pair::Loader
|
|
21
24
|
Dir[ @fixture_file_pattern ].each do |filename|
|
22
25
|
id = extract_id filename
|
23
26
|
fixture = load_file filename
|
24
|
-
|
25
|
-
|
27
|
+
if fixture
|
28
|
+
@fixtures[id] = fixture
|
29
|
+
@logger.info "loaded fixture '#{id}'"
|
30
|
+
end
|
26
31
|
end
|
27
32
|
@fixtures.freeze
|
28
33
|
end
|
29
34
|
|
30
35
|
def load_pairs
|
31
36
|
Dir[ @pair_file_pattern ].each do |filename|
|
32
|
-
|
33
|
-
pair = load_file filename
|
34
|
-
@pairs[id] = pair_with_imports pair if pair
|
35
|
-
@logger.info "loaded pair '#{id}'"
|
37
|
+
load_pair filename
|
36
38
|
end
|
37
39
|
@pairs.freeze
|
38
40
|
end
|
39
41
|
|
42
|
+
def load_pair(filename)
|
43
|
+
id = extract_id filename
|
44
|
+
pair = load_file filename
|
45
|
+
if pair
|
46
|
+
@validator.validate(pair)
|
47
|
+
@pairs[id] = pair_with_imports pair
|
48
|
+
@logger.info "loaded pair '#{id}'"
|
49
|
+
end
|
50
|
+
rescue Holoserve::Pair::Validator::InvalidError => error
|
51
|
+
@logger.error error.inspect
|
52
|
+
end
|
53
|
+
|
40
54
|
def extract_id(filename)
|
41
55
|
File.basename filename, ".*"
|
42
56
|
end
|
@@ -52,18 +66,21 @@ class Holoserve::Pair::Loader
|
|
52
66
|
rescue JSON::ParserError
|
53
67
|
nil
|
54
68
|
end
|
55
|
-
|
69
|
+
end
|
56
70
|
Holoserve::Tool::Hash::KeySymbolizer.new(data).hash
|
57
71
|
end
|
58
72
|
|
59
73
|
def pair_with_imports(pair)
|
60
|
-
result = {
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
(pair[:responses] || { }).each do |id, response|
|
65
|
-
result[:responses][id] = Holoserve::Fixture::Importer.new(response, @fixtures).result
|
74
|
+
result = { :requests => { }, :responses => { } }
|
75
|
+
|
76
|
+
pair[:requests].each do |variant, request|
|
77
|
+
result[:requests][variant] = Holoserve::Fixture::Importer.new(request, @fixtures).result
|
66
78
|
end
|
79
|
+
|
80
|
+
pair[:responses].each do |variant, response|
|
81
|
+
result[:responses][variant] = Holoserve::Fixture::Importer.new(response, @fixtures).result
|
82
|
+
end
|
83
|
+
|
67
84
|
result
|
68
85
|
end
|
69
86
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'kwalify'
|
3
|
+
|
4
|
+
class Holoserve::Pair::Validator
|
5
|
+
|
6
|
+
class Error < StandardError
|
7
|
+
|
8
|
+
def initialize(errors)
|
9
|
+
@errors = errors
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
"<#{self.class} error count = #{@errors.size}>"
|
14
|
+
end
|
15
|
+
|
16
|
+
def inspect
|
17
|
+
"#{self.class}\n " + @errors.join("\n ")
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class InvalidError < Error; end
|
23
|
+
class InvalidSchemaError < Error; end
|
24
|
+
|
25
|
+
attr_accessor :schema_path
|
26
|
+
|
27
|
+
def initialize(schema_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "schema", "schema.yaml")))
|
28
|
+
@schema_path = schema_path
|
29
|
+
@meta_validator = Kwalify::MetaValidator.instance
|
30
|
+
load_schema
|
31
|
+
@validator = Kwalify::Validator.new(@schema)
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate(hash)
|
35
|
+
errors = @validator.validate(hash)
|
36
|
+
raise InvalidError, errors if errors && !errors.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def load_schema
|
42
|
+
@schema = Kwalify::Yaml::load_file(@schema_path)
|
43
|
+
errors = @meta_validator.validate(@schema)
|
44
|
+
raise InvalidSchemaError, errors if errors && !errors.empty?
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/lib/holoserve/pair.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
class Holoserve::Request::Selector
|
3
|
+
|
4
|
+
attr_accessor :request
|
5
|
+
|
6
|
+
def initialize(request, request_subsets)
|
7
|
+
@request, @request_subsets = request, request_subsets
|
8
|
+
end
|
9
|
+
|
10
|
+
def selection
|
11
|
+
if Holoserve::Tool::Hash::Matcher.new(@request, @request_subsets[:default]).match?
|
12
|
+
@request_subsets.each do |variant, subset|
|
13
|
+
next if variant == :default
|
14
|
+
return variant if Holoserve::Tool::Hash::Matcher.new(@request, subset).match?
|
15
|
+
end
|
16
|
+
return :default
|
17
|
+
end
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/lib/holoserve/request.rb
CHANGED
@@ -2,6 +2,6 @@
|
|
2
2
|
module Holoserve::Request
|
3
3
|
|
4
4
|
autoload :Decomposer, File.join(File.dirname(__FILE__), "request", "decomposer")
|
5
|
-
autoload :
|
5
|
+
autoload :Selector, File.join(File.dirname(__FILE__), "request", "selector")
|
6
6
|
|
7
7
|
end
|
@@ -24,26 +24,19 @@ class Holoserve::Response::Selector
|
|
24
24
|
@sandbox = Sandbox.new state, logger
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
@responses
|
29
|
-
|
30
|
-
{ }
|
31
|
-
end
|
32
|
-
|
33
|
-
def selected_responses
|
34
|
-
result = [ ]
|
35
|
-
(@responses || { }).each do |line, response|
|
36
|
-
next if line.to_s == "default"
|
27
|
+
def selection
|
28
|
+
@responses.each do |key, response|
|
29
|
+
next if key.to_sym == :default
|
37
30
|
begin
|
38
31
|
match = @sandbox.instance_eval do
|
39
|
-
eval
|
32
|
+
eval response[:condition]
|
40
33
|
end
|
41
|
-
|
34
|
+
return key.to_sym if match
|
42
35
|
rescue Object => error
|
43
36
|
@logger.error error.inspect
|
44
37
|
end
|
45
38
|
end
|
46
|
-
|
39
|
+
@responses.has_key?(:default) ? :default : nil
|
47
40
|
end
|
48
41
|
|
49
42
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
class Holoserve::Tool::Hash::Matcher
|
3
|
+
|
4
|
+
attr_accessor :hash
|
5
|
+
attr_accessor :subset
|
6
|
+
|
7
|
+
def initialize(hash, subset)
|
8
|
+
@hash, @subset = hash, subset
|
9
|
+
end
|
10
|
+
|
11
|
+
def match?
|
12
|
+
return false if @hash.length < @subset.length
|
13
|
+
@subset.each do |key, value|
|
14
|
+
if @hash.has_key?(key)
|
15
|
+
return false unless match_value?(@hash[key], value)
|
16
|
+
else
|
17
|
+
return false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def match_value?(value_one, value_two)
|
26
|
+
if value_one.is_a?(Hash) && value_two.is_a?(Hash)
|
27
|
+
return false unless match_hash?(value_one, value_two)
|
28
|
+
elsif value_one.is_a?(Array) && value_two.is_a?(Array)
|
29
|
+
return false unless match_array?(value_one, value_two)
|
30
|
+
else
|
31
|
+
return false unless value_one == value_two
|
32
|
+
end
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def match_hash?(hash, subset)
|
37
|
+
tmp = Holoserve::Tool::Hash::Matcher.new(hash, subset)
|
38
|
+
return false unless tmp.match?
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
def match_array?(array, subset)
|
43
|
+
return false if array.length < subset.length
|
44
|
+
subset.each_index do |i|
|
45
|
+
if subset[i].is_a?(Hash) && array[i].is_a?(Hash)
|
46
|
+
return false unless match_hash?(array[i], subset[i])
|
47
|
+
elsif subset[i].is_a?(Array) && array[i].is_a?(Array)
|
48
|
+
return false unless match_array?(array[i], subset[i])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
true
|
52
|
+
end
|
53
|
+
end
|
data/lib/holoserve/tool/hash.rb
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "helper"))
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
describe Holoserve::Pair::Validator do
|
5
|
+
|
6
|
+
let(:valid_schema_path) do
|
7
|
+
File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "..", "schema", "schema.yaml"))
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:invalid_schema_path) do
|
11
|
+
File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "..", "features", "pairs", "invalid", "test_invalid_schema.yaml"))
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:valid_hash) do
|
15
|
+
file = YAML::load_file(File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "..", "features", "pairs", "test_evaluation.yaml")))
|
16
|
+
Holoserve::Tool::Hash::KeySymbolizer.new(file).hash
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:invalid_hash) do
|
20
|
+
file = YAML::load_file(File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "..", "features", "pairs", "invalid", "test_invalid_headers.yaml")))
|
21
|
+
Holoserve::Tool::Hash::KeySymbolizer.new(file).hash
|
22
|
+
end
|
23
|
+
|
24
|
+
subject { described_class.new valid_schema_path }
|
25
|
+
|
26
|
+
describe "#initialize" do
|
27
|
+
|
28
|
+
it "should raise an InvalidSchemaError if the schema file is invalid" do
|
29
|
+
lambda do
|
30
|
+
described_class.new invalid_schema_path
|
31
|
+
end.should raise_error(described_class::InvalidSchemaError)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#validate" do
|
37
|
+
|
38
|
+
it "should return true if a valid pair file is provided" do
|
39
|
+
lambda do
|
40
|
+
subject.validate(valid_hash)
|
41
|
+
end.should_not raise_error
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return false if an invalid pair file is provided" do
|
45
|
+
lambda do
|
46
|
+
subject.validate(invalid_hash)
|
47
|
+
end.should raise_error(described_class::InvalidError)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "helper"))
|
2
|
+
|
3
|
+
describe Holoserve::Request::Selector do
|
4
|
+
|
5
|
+
let(:subsets) do
|
6
|
+
{
|
7
|
+
:default => {
|
8
|
+
:method => "GET",
|
9
|
+
:path => "/test"
|
10
|
+
},
|
11
|
+
:test => {
|
12
|
+
:headers => {
|
13
|
+
:HTTP_TEST => "value"
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:variant_matching_request) do
|
20
|
+
{
|
21
|
+
:method => "GET",
|
22
|
+
:path => "/test",
|
23
|
+
:headers => {
|
24
|
+
:HTTP_TEST => "value",
|
25
|
+
:HTTP_HOST => "localhost"
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:invalid_request) do
|
31
|
+
{
|
32
|
+
:method => "POST",
|
33
|
+
:other_test => {
|
34
|
+
:key => "value"
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
let(:default_matching_request) do
|
40
|
+
{
|
41
|
+
:method => "GET",
|
42
|
+
:path => "/test",
|
43
|
+
:parameters => {
|
44
|
+
:test => "value"
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
subject { described_class.new invalid_request, subsets }
|
50
|
+
|
51
|
+
describe "#selection" do
|
52
|
+
|
53
|
+
it "should return nil if request is not matching default nor any other subset" do
|
54
|
+
subject.selection.should be_nil
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should return :default if the default subset is matched" do
|
58
|
+
subject.request = default_matching_request
|
59
|
+
subject.selection.should == :default
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should return :test if the corresponding subset is matched" do
|
63
|
+
subject.request = variant_matching_request
|
64
|
+
subject.selection.should == :test
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require File.expand_path("../../../../helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe Holoserve::Tool::Hash::Matcher do
|
4
|
+
|
5
|
+
let(:hash) do
|
6
|
+
{
|
7
|
+
:test => "value",
|
8
|
+
:nested => {
|
9
|
+
:unspecified => "value",
|
10
|
+
:another => "test value"
|
11
|
+
},
|
12
|
+
:unspecified => "value",
|
13
|
+
:nested_array => [{:hash => "value", :unspecified => "value", :morehash => {:test => "value", :unspecified => "value", :array => [{:test => "value"}]}}]
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:matching_subset) do
|
18
|
+
{
|
19
|
+
:test => "value"
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:matching_subset_with_nested_hash) do
|
24
|
+
{
|
25
|
+
:nested => {
|
26
|
+
:another => "test value"
|
27
|
+
}
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:matching_subset_with_nested_array) do
|
32
|
+
{
|
33
|
+
:nested_array => [{:hash => "value"}]
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
let(:matching_subset_with_nested_array_and_nested_hash) do
|
38
|
+
{
|
39
|
+
:nested_array => [{:hash => "value", :morehash => {:test => "value"}}]
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
let(:matching_subset_with_nested_array_and_nested_hash_and_nested_array) do
|
44
|
+
{
|
45
|
+
:nested_array => [{:hash => "value", :morehash => {:test => "value", :array => [{:test => "value"}]}}]
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
let(:mismatching_subset) do
|
50
|
+
{
|
51
|
+
:test => "another value"
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
let(:mismatching_subset_with_nested_hash) do
|
56
|
+
{
|
57
|
+
:nested => {
|
58
|
+
:another => "another value"
|
59
|
+
}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
let(:mismatching_subset_with_nested_array) do
|
64
|
+
{
|
65
|
+
:nested_array => [{:hash => "other value"}]
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
let(:mismatching_subset_with_nested_array_and_nested_hash) do
|
70
|
+
{
|
71
|
+
:nested_array => [{:hash => "value", :morehash => {:test => "other value"}}]
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
let(:mismatching_subset_with_nested_array_and_nested_hash_and_nested_array) do
|
76
|
+
{
|
77
|
+
:nested_array => [{:hash => "value", :morehash => {:test => "value", :array => [{:test => "other value"}]}}]
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
subject { described_class.new hash, matching_subset }
|
82
|
+
|
83
|
+
describe "#match?" do
|
84
|
+
|
85
|
+
it "should return true if a matching subset is provided" do
|
86
|
+
subject.match?.should be_true
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should return false if a mismatching subset is provided" do
|
90
|
+
subject.subset = mismatching_subset
|
91
|
+
subject.match?.should be_false
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should return true if a matching subset with nested hash is provided" do
|
95
|
+
subject.subset = matching_subset_with_nested_hash
|
96
|
+
subject.match?.should be_true
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should return false if a mismatching subset with nested hash is provided" do
|
100
|
+
subject.subset = mismatching_subset_with_nested_hash
|
101
|
+
subject.match?.should be_false
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should return true if a matching subset with nested array is provided" do
|
105
|
+
subject.subset = matching_subset_with_nested_array
|
106
|
+
subject.match?.should be_true
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should return false if a mismatching subset with nested array is provided" do
|
110
|
+
subject.subset = mismatching_subset_with_nested_array
|
111
|
+
subject.match?.should be_false
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should return true if a matching subset with nested array and nested hash is provided" do
|
115
|
+
subject.subset = matching_subset_with_nested_array_and_nested_hash
|
116
|
+
subject.match?.should be_true
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should return false if a mismatching subset with nested array and nested hash is provided" do
|
120
|
+
subject.subset = mismatching_subset_with_nested_array_and_nested_hash
|
121
|
+
subject.match?.should be_false
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should return true if a matching subset with nested array and nested hash and nested array is provided" do
|
125
|
+
subject.subset = matching_subset_with_nested_array_and_nested_hash_and_nested_array
|
126
|
+
subject.match?.should be_true
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should return false if a mismatching subset with nested array and nested hash and nested array is provided" do
|
130
|
+
subject.subset = mismatching_subset_with_nested_array_and_nested_hash_and_nested_array
|
131
|
+
subject.match?.should be_false
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
metadata
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: holoserve
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Philipp Brüll
|
9
|
+
- Maximilian Hoffmann
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date: 2012-
|
13
|
+
date: 2012-06-22 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: goliath
|
16
|
-
requirement: &
|
17
|
+
requirement: &70242257528700 !ruby/object:Gem::Requirement
|
17
18
|
none: false
|
18
19
|
requirements:
|
19
20
|
- - ! '>='
|
@@ -21,10 +22,54 @@ dependencies:
|
|
21
22
|
version: '0'
|
22
23
|
type: :runtime
|
23
24
|
prerelease: false
|
24
|
-
version_requirements: *
|
25
|
+
version_requirements: *70242257528700
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: slim
|
28
|
+
requirement: &70242257527940 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *70242257527940
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: sass
|
39
|
+
requirement: &70242257526740 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
type: :runtime
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *70242257526740
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: coffee-script
|
50
|
+
requirement: &70242257526220 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :runtime
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *70242257526220
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: kwalify
|
61
|
+
requirement: &70242257525580 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :runtime
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *70242257525580
|
25
70
|
- !ruby/object:Gem::Dependency
|
26
71
|
name: rake
|
27
|
-
requirement: &
|
72
|
+
requirement: &70242257523600 !ruby/object:Gem::Requirement
|
28
73
|
none: false
|
29
74
|
requirements:
|
30
75
|
- - ! '>='
|
@@ -32,10 +77,10 @@ dependencies:
|
|
32
77
|
version: '0'
|
33
78
|
type: :development
|
34
79
|
prerelease: false
|
35
|
-
version_requirements: *
|
80
|
+
version_requirements: *70242257523600
|
36
81
|
- !ruby/object:Gem::Dependency
|
37
82
|
name: rdoc
|
38
|
-
requirement: &
|
83
|
+
requirement: &70242257522300 !ruby/object:Gem::Requirement
|
39
84
|
none: false
|
40
85
|
requirements:
|
41
86
|
- - ! '>='
|
@@ -43,10 +88,10 @@ dependencies:
|
|
43
88
|
version: '0'
|
44
89
|
type: :development
|
45
90
|
prerelease: false
|
46
|
-
version_requirements: *
|
91
|
+
version_requirements: *70242257522300
|
47
92
|
- !ruby/object:Gem::Dependency
|
48
93
|
name: cucumber
|
49
|
-
requirement: &
|
94
|
+
requirement: &70242257537280 !ruby/object:Gem::Requirement
|
50
95
|
none: false
|
51
96
|
requirements:
|
52
97
|
- - ! '>='
|
@@ -54,10 +99,10 @@ dependencies:
|
|
54
99
|
version: '0'
|
55
100
|
type: :development
|
56
101
|
prerelease: false
|
57
|
-
version_requirements: *
|
102
|
+
version_requirements: *70242257537280
|
58
103
|
- !ruby/object:Gem::Dependency
|
59
104
|
name: rspec
|
60
|
-
requirement: &
|
105
|
+
requirement: &70242257536160 !ruby/object:Gem::Requirement
|
61
106
|
none: false
|
62
107
|
requirements:
|
63
108
|
- - ! '>='
|
@@ -65,10 +110,10 @@ dependencies:
|
|
65
110
|
version: '0'
|
66
111
|
type: :development
|
67
112
|
prerelease: false
|
68
|
-
version_requirements: *
|
113
|
+
version_requirements: *70242257536160
|
69
114
|
- !ruby/object:Gem::Dependency
|
70
115
|
name: transport
|
71
|
-
requirement: &
|
116
|
+
requirement: &70242257535520 !ruby/object:Gem::Requirement
|
72
117
|
none: false
|
73
118
|
requirements:
|
74
119
|
- - ! '>='
|
@@ -76,10 +121,10 @@ dependencies:
|
|
76
121
|
version: '0'
|
77
122
|
type: :development
|
78
123
|
prerelease: false
|
79
|
-
version_requirements: *
|
124
|
+
version_requirements: *70242257535520
|
80
125
|
- !ruby/object:Gem::Dependency
|
81
126
|
name: oauth
|
82
|
-
requirement: &
|
127
|
+
requirement: &70242257534980 !ruby/object:Gem::Requirement
|
83
128
|
none: false
|
84
129
|
requirements:
|
85
130
|
- - ! '>='
|
@@ -87,7 +132,7 @@ dependencies:
|
|
87
132
|
version: '0'
|
88
133
|
type: :development
|
89
134
|
prerelease: false
|
90
|
-
version_requirements: *
|
135
|
+
version_requirements: *70242257534980
|
91
136
|
description: This tool can be used to fake webservice APIs for testing proposals.
|
92
137
|
email: philipp.bruell@skrill.com
|
93
138
|
executables:
|
@@ -105,16 +150,19 @@ files:
|
|
105
150
|
- lib/holoserve/fixture.rb
|
106
151
|
- lib/holoserve/interface/control/bucket.rb
|
107
152
|
- lib/holoserve/interface/control/history.rb
|
153
|
+
- lib/holoserve/interface/control/index.rb
|
108
154
|
- lib/holoserve/interface/control/pair.rb
|
109
155
|
- lib/holoserve/interface/control/state.rb
|
110
156
|
- lib/holoserve/interface/control.rb
|
157
|
+
- lib/holoserve/interface/event.rb
|
111
158
|
- lib/holoserve/interface/fake.rb
|
112
159
|
- lib/holoserve/interface.rb
|
113
160
|
- lib/holoserve/pair/finder.rb
|
114
161
|
- lib/holoserve/pair/loader.rb
|
162
|
+
- lib/holoserve/pair/validator.rb
|
115
163
|
- lib/holoserve/pair.rb
|
116
164
|
- lib/holoserve/request/decomposer.rb
|
117
|
-
- lib/holoserve/request/
|
165
|
+
- lib/holoserve/request/selector.rb
|
118
166
|
- lib/holoserve/request.rb
|
119
167
|
- lib/holoserve/response/combiner.rb
|
120
168
|
- lib/holoserve/response/composer.rb
|
@@ -124,6 +172,7 @@ files:
|
|
124
172
|
- lib/holoserve/state.rb
|
125
173
|
- lib/holoserve/tool/data_path.rb
|
126
174
|
- lib/holoserve/tool/hash/key_symbolizer.rb
|
175
|
+
- lib/holoserve/tool/hash/matcher.rb
|
127
176
|
- lib/holoserve/tool/hash.rb
|
128
177
|
- lib/holoserve/tool/merger.rb
|
129
178
|
- lib/holoserve/tool/uploader.rb
|
@@ -131,7 +180,10 @@ files:
|
|
131
180
|
- lib/holoserve.rb
|
132
181
|
- spec/helper.rb
|
133
182
|
- spec/lib/holoserve/fixture/importer_spec.rb
|
183
|
+
- spec/lib/holoserve/pair/validator_spec.rb
|
184
|
+
- spec/lib/holoserve/request/selector_spec.rb
|
134
185
|
- spec/lib/holoserve/tool/data_path_spec.rb
|
186
|
+
- spec/lib/holoserve/tool/hash/matcher_spec.rb
|
135
187
|
- spec/lib/holoserve/tool/merger_spec.rb
|
136
188
|
- spec/lib/holoserve_spec.rb
|
137
189
|
homepage: http://github.com/skrill/holoserve
|
@@ -148,7 +200,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
148
200
|
version: '0'
|
149
201
|
segments:
|
150
202
|
- 0
|
151
|
-
hash:
|
203
|
+
hash: 3487198030302980531
|
152
204
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
205
|
none: false
|
154
206
|
requirements:
|
@@ -163,6 +215,9 @@ specification_version: 3
|
|
163
215
|
summary: Tool to fake HTTP APIs.
|
164
216
|
test_files:
|
165
217
|
- spec/lib/holoserve/fixture/importer_spec.rb
|
218
|
+
- spec/lib/holoserve/pair/validator_spec.rb
|
219
|
+
- spec/lib/holoserve/request/selector_spec.rb
|
166
220
|
- spec/lib/holoserve/tool/data_path_spec.rb
|
221
|
+
- spec/lib/holoserve/tool/hash/matcher_spec.rb
|
167
222
|
- spec/lib/holoserve/tool/merger_spec.rb
|
168
223
|
- spec/lib/holoserve_spec.rb
|
@@ -1,74 +0,0 @@
|
|
1
|
-
|
2
|
-
class Holoserve::Request::Matcher
|
3
|
-
|
4
|
-
def initialize(request, request_subset)
|
5
|
-
@request, @request_subset = request, request_subset
|
6
|
-
end
|
7
|
-
|
8
|
-
def match?
|
9
|
-
match_method? &&
|
10
|
-
match_path? &&
|
11
|
-
match_headers? &&
|
12
|
-
match_body? &&
|
13
|
-
match_parameters? &&
|
14
|
-
match_oauth? &&
|
15
|
-
match_json?
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def match_method?
|
21
|
-
@request_subset[:method] ?
|
22
|
-
@request[:method] == @request_subset[:method] :
|
23
|
-
true
|
24
|
-
end
|
25
|
-
|
26
|
-
def match_path?
|
27
|
-
@request_subset[:path] ?
|
28
|
-
@request[:path] == @request_subset[:path] :
|
29
|
-
true
|
30
|
-
end
|
31
|
-
|
32
|
-
def match_headers?
|
33
|
-
match = true
|
34
|
-
(@request_subset[:headers] || { }).each do |key, value|
|
35
|
-
match &&= @request[:headers][key] == value
|
36
|
-
end
|
37
|
-
match
|
38
|
-
end
|
39
|
-
|
40
|
-
def match_body?
|
41
|
-
@request_subset[:body] ?
|
42
|
-
@request[:body] == @request_subset[:body] :
|
43
|
-
true
|
44
|
-
end
|
45
|
-
|
46
|
-
def match_parameters?
|
47
|
-
match = true
|
48
|
-
(@request_subset[:parameters] || { }).each do |key, value|
|
49
|
-
match &&= @request[:parameters].is_a?(Hash) && (@request[:parameters][key] == value)
|
50
|
-
end
|
51
|
-
match
|
52
|
-
end
|
53
|
-
|
54
|
-
def match_oauth?
|
55
|
-
match = true
|
56
|
-
(@request_subset[:oauth] || { }).each do |key, value|
|
57
|
-
match &&= @request[:oauth].is_a?(Hash) && (@request[:oauth][key] == value)
|
58
|
-
end
|
59
|
-
match
|
60
|
-
end
|
61
|
-
|
62
|
-
def match_json?
|
63
|
-
match_hash? :json
|
64
|
-
end
|
65
|
-
|
66
|
-
def match_hash?(hash_key)
|
67
|
-
match = true
|
68
|
-
(@request_subset[hash_key] || { }).each do |key, value|
|
69
|
-
match &&= @request[hash_key].is_a?(Hash) && (@request[hash_key][key] == value)
|
70
|
-
end
|
71
|
-
match
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|