webspicy 0.15.7 → 0.16.3
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/README.md +71 -24
- data/bin/webspicy +30 -14
- data/examples/restful/Gemfile +2 -2
- data/examples/restful/Gemfile.lock +53 -33
- data/examples/restful/Rakefile +0 -1
- data/examples/restful/app.rb +4 -1
- data/examples/restful/webspicy/config.rb +8 -0
- data/examples/restful/webspicy/rack.rb +1 -1
- data/examples/restful/webspicy/real.rb +1 -1
- data/examples/restful/webspicy/schema.fio +2 -2
- data/examples/restful/webspicy/support/must_be_authenticated.rb +2 -2
- data/examples/restful/webspicy/support/todo_removed.rb +18 -0
- data/examples/restful/webspicy/todo/deleteTodo.yml +4 -1
- data/examples/restful/webspicy/todo/getTodoSingleServiceFormat.yml +46 -0
- data/examples/restful/webspicy/todo/options.yml +1 -1
- data/examples/restful/webspicy/todo/patchTodo.yml +3 -0
- data/examples/restful/webspicy/todo/postFile.yml +1 -1
- data/examples/single_spec/spec.yml +59 -0
- data/examples/website/config.rb +2 -0
- data/examples/website/schema.fio +1 -0
- data/examples/website/specification/get-http.yml +30 -0
- data/examples/website/specification/get-https.yml +30 -0
- data/lib/finitio/webspicy/scalars.fio +25 -0
- data/lib/webspicy.rb +48 -17
- data/lib/webspicy/checker.rb +2 -2
- data/lib/webspicy/configuration.rb +70 -14
- data/lib/webspicy/configuration/scope.rb +162 -0
- data/lib/webspicy/configuration/single_url.rb +58 -0
- data/lib/webspicy/configuration/single_yml_file.rb +30 -0
- data/lib/webspicy/formaldoc.fio +23 -8
- data/lib/webspicy/mocker.rb +8 -8
- data/lib/webspicy/mocker/config.ru +5 -0
- data/lib/webspicy/openapi.rb +1 -0
- data/lib/webspicy/openapi/generator.rb +127 -0
- data/lib/webspicy/{resource.rb → specification.rb} +28 -5
- data/lib/webspicy/specification/file_upload.rb +37 -0
- data/lib/webspicy/specification/postcondition.rb +16 -0
- data/lib/webspicy/specification/precondition.rb +19 -0
- data/lib/webspicy/specification/precondition/global_request_headers.rb +35 -0
- data/lib/webspicy/specification/precondition/robust_to_invalid_input.rb +68 -0
- data/lib/webspicy/{resource → specification}/service.rb +11 -6
- data/lib/webspicy/specification/test_case.rb +139 -0
- data/lib/webspicy/support.rb +1 -0
- data/lib/webspicy/support/colorize.rb +28 -0
- data/lib/webspicy/support/status_range.rb +6 -1
- data/lib/webspicy/tester.rb +16 -11
- data/lib/webspicy/tester/asserter.rb +3 -2
- data/lib/webspicy/tester/assertions.rb +5 -1
- data/lib/webspicy/tester/client.rb +63 -0
- data/lib/webspicy/tester/client/http_client.rb +154 -0
- data/lib/webspicy/tester/client/rack_test_client.rb +188 -0
- data/lib/webspicy/tester/client/support.rb +65 -0
- data/lib/webspicy/tester/invocation.rb +218 -0
- data/lib/webspicy/tester/rspec_asserter.rb +108 -0
- data/lib/webspicy/tester/rspec_matchers.rb +104 -0
- data/lib/webspicy/version.rb +2 -2
- data/spec/{unit/spec_helper.rb → spec_helper.rb} +0 -0
- data/spec/unit/configuration/scope/test_each_service.rb +49 -0
- data/spec/unit/configuration/scope/test_each_specification.rb +68 -0
- data/spec/unit/configuration/scope/test_expand_example.rb +65 -0
- data/spec/unit/configuration/scope/test_to_real_url.rb +82 -0
- data/spec/unit/openapi/test_generator.rb +28 -0
- data/spec/unit/specification/precondition/test_global_request_headers.rb +42 -0
- data/spec/unit/{resource → specification}/service/test_dress_params.rb +2 -2
- data/spec/unit/specification/test_case/test_mutate.rb +24 -0
- data/spec/unit/{resource → specification}/test_instantiate_url.rb +5 -5
- data/spec/unit/{resource → specification}/test_url_placeholders.rb +4 -4
- data/spec/unit/test_configuration.rb +24 -7
- data/spec/unit/tester/client/test_around.rb +61 -0
- data/spec/unit/tester/test_asserter.rb +51 -0
- data/spec/unit/tester/test_assertions.rb +4 -4
- data/tasks/test.rake +3 -1
- metadata +88 -45
- data/LICENSE.md +0 -22
- data/lib/webspicy/client.rb +0 -61
- data/lib/webspicy/client/http_client.rb +0 -145
- data/lib/webspicy/client/rack_test_client.rb +0 -181
- data/lib/webspicy/client/support.rb +0 -48
- data/lib/webspicy/file_upload.rb +0 -35
- data/lib/webspicy/postcondition.rb +0 -14
- data/lib/webspicy/precondition.rb +0 -15
- data/lib/webspicy/resource/service/invocation.rb +0 -212
- data/lib/webspicy/resource/service/test_case.rb +0 -132
- data/lib/webspicy/scope.rb +0 -160
- data/spec/unit/client/test_around.rb +0 -59
- data/spec/unit/scope/test_each_resource.rb +0 -66
- data/spec/unit/scope/test_each_service.rb +0 -47
- data/spec/unit/scope/test_expand_example.rb +0 -63
- data/spec/unit/scope/test_to_real_url.rb +0 -80
data/lib/webspicy/file_upload.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
module Webspicy
|
2
|
-
class FileUpload
|
3
|
-
|
4
|
-
def initialize(raw)
|
5
|
-
@path = raw[:path]
|
6
|
-
@content_type = raw[:content_type]
|
7
|
-
@param_name = raw[:param_name] || "file"
|
8
|
-
end
|
9
|
-
|
10
|
-
attr_reader :path, :content_type, :param_name
|
11
|
-
|
12
|
-
def self.info(raw)
|
13
|
-
new(raw)
|
14
|
-
end
|
15
|
-
|
16
|
-
def locate(resource)
|
17
|
-
FileUpload.new({
|
18
|
-
path: resource.locate(path),
|
19
|
-
content_type: content_type
|
20
|
-
})
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_info
|
24
|
-
{ path: path.to_s,
|
25
|
-
content_type: content_type,
|
26
|
-
param_name: param_name }
|
27
|
-
end
|
28
|
-
|
29
|
-
def to_s
|
30
|
-
"FileUpload(#{to_info})"
|
31
|
-
end
|
32
|
-
alias :inspect :to_s
|
33
|
-
|
34
|
-
end # class FileUpload
|
35
|
-
end # module Webspicy
|
@@ -1,212 +0,0 @@
|
|
1
|
-
module Webspicy
|
2
|
-
class Resource
|
3
|
-
class Service
|
4
|
-
class Invocation
|
5
|
-
|
6
|
-
def initialize(service, test_case, response, client)
|
7
|
-
@service = service
|
8
|
-
@test_case = test_case
|
9
|
-
@response = response
|
10
|
-
@client = client
|
11
|
-
end
|
12
|
-
|
13
|
-
attr_reader :service, :test_case, :response, :client
|
14
|
-
|
15
|
-
def errors
|
16
|
-
@errors ||= begin
|
17
|
-
errs = [
|
18
|
-
[:expected_status_unmet, true],
|
19
|
-
[:expected_content_type_unmet, !test_case.is_expected_status?(204)],
|
20
|
-
[:expected_headers_unmet, test_case.has_expected_headers?],
|
21
|
-
[:expected_schema_unmet, !test_case.is_expected_status?(204)],
|
22
|
-
[:assertions_unmet, test_case.has_assertions?],
|
23
|
-
[:postconditions_unmet, test_case.service.has_postconditions? && !test_case.counterexample?],
|
24
|
-
[:expected_error_unmet, test_case.has_expected_error?]
|
25
|
-
].map do |(expectation,only_if)|
|
26
|
-
next unless only_if
|
27
|
-
begin
|
28
|
-
self.send(expectation)
|
29
|
-
rescue => ex
|
30
|
-
ex.message
|
31
|
-
end
|
32
|
-
end
|
33
|
-
errs.compact
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def has_error?
|
38
|
-
!errors.empty?
|
39
|
-
end
|
40
|
-
|
41
|
-
### Getters on response
|
42
|
-
|
43
|
-
def response_code
|
44
|
-
code = response.status
|
45
|
-
code = code.code unless code.is_a?(Integer)
|
46
|
-
code
|
47
|
-
end
|
48
|
-
|
49
|
-
### Query methods
|
50
|
-
|
51
|
-
def done?
|
52
|
-
!response.nil?
|
53
|
-
end
|
54
|
-
|
55
|
-
def is_expected_success?
|
56
|
-
test_case.expected_status.to_i >= 200 && test_case.expected_status.to_i < 300
|
57
|
-
end
|
58
|
-
|
59
|
-
def is_success?
|
60
|
-
response_code >= 200 && response_code < 300
|
61
|
-
end
|
62
|
-
|
63
|
-
def is_empty_response?
|
64
|
-
response_code == 204
|
65
|
-
end
|
66
|
-
|
67
|
-
def is_redirect?
|
68
|
-
response_code >= 300 && response_code < 400
|
69
|
-
end
|
70
|
-
|
71
|
-
### Check of HTTP status
|
72
|
-
|
73
|
-
def expected_status_unmet
|
74
|
-
expected = test_case.expected_status
|
75
|
-
got = response.status
|
76
|
-
expected === got ? nil : "#{expected} !== #{got}"
|
77
|
-
end
|
78
|
-
|
79
|
-
def meets_expected_status?
|
80
|
-
expected_status_unmet.nil?
|
81
|
-
end
|
82
|
-
|
83
|
-
### Check of the expected output type
|
84
|
-
|
85
|
-
def expected_content_type_unmet
|
86
|
-
ect = test_case.expected_content_type
|
87
|
-
got = response.content_type
|
88
|
-
got = got.mime_type if got.respond_to?(:mime_type)
|
89
|
-
if ect.nil?
|
90
|
-
got.nil? ? nil : "#{ect} != #{got}"
|
91
|
-
else
|
92
|
-
got.to_s.start_with?(ect.to_s) ? nil : "#{ect} != #{got}"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def meets_expected_content_type?
|
97
|
-
expected_content_type_unmet.nil?
|
98
|
-
end
|
99
|
-
|
100
|
-
### Check of output schema
|
101
|
-
|
102
|
-
def expected_schema_unmet
|
103
|
-
if is_empty_response?
|
104
|
-
body = response.body.to_s.strip
|
105
|
-
body.empty? ? nil : "Expected empty body, got #{body}"
|
106
|
-
elsif is_redirect?
|
107
|
-
else
|
108
|
-
case dressed_body
|
109
|
-
when Finitio::TypeError
|
110
|
-
rc = dressed_body.root_cause
|
111
|
-
"#{rc.message} (#{rc.location ? rc.location : 'unknown location'})"
|
112
|
-
when StandardError
|
113
|
-
dressed_body.message
|
114
|
-
else nil
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
def meets_expected_schema?
|
120
|
-
expected_schema_unmet.nil?
|
121
|
-
end
|
122
|
-
|
123
|
-
### Check of assertions
|
124
|
-
|
125
|
-
def assertions_unmet
|
126
|
-
unmet = []
|
127
|
-
asserter = Tester::Asserter.new(dressed_body)
|
128
|
-
test_case.assert.each do |assert|
|
129
|
-
begin
|
130
|
-
asserter.instance_eval(assert)
|
131
|
-
rescue => ex
|
132
|
-
unmet << ex.message
|
133
|
-
end
|
134
|
-
end
|
135
|
-
unmet.empty? ? nil : unmet.join("\n")
|
136
|
-
end
|
137
|
-
|
138
|
-
def value_equal(exp, got)
|
139
|
-
case exp
|
140
|
-
when Hash
|
141
|
-
exp.all?{|(k,v)|
|
142
|
-
got[k] == v
|
143
|
-
}
|
144
|
-
else
|
145
|
-
exp == got
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
### Check of expected error message
|
150
|
-
|
151
|
-
def expected_error_unmet
|
152
|
-
expected = test_case.expected_error
|
153
|
-
case test_case.expected_content_type
|
154
|
-
when %r{json}
|
155
|
-
got = meets_expected_schema? ? dressed_body[:description] : response.body
|
156
|
-
expected == got ? nil : "`#{expected}` vs. `#{got}`"
|
157
|
-
else
|
158
|
-
dressed_body.include?(expected) ? nil : "#{expected} not found" unless expected.nil?
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
### Check of expected headers
|
163
|
-
|
164
|
-
def expected_headers_unmet
|
165
|
-
unmet = []
|
166
|
-
expected = test_case.expected_headers
|
167
|
-
expected.each_pair do |k,v|
|
168
|
-
got = response.headers[k]
|
169
|
-
unmet << "#{v} expected for #{k}, got #{got}" unless (got == v)
|
170
|
-
end
|
171
|
-
unmet.empty? ? nil : unmet.join("\n")
|
172
|
-
end
|
173
|
-
|
174
|
-
### Check of postconditions
|
175
|
-
|
176
|
-
def postconditions_unmet
|
177
|
-
failures = service.postconditions.map{|post|
|
178
|
-
post.check(self)
|
179
|
-
}.compact
|
180
|
-
failures.empty? ? nil : failures.join("\n")
|
181
|
-
end
|
182
|
-
|
183
|
-
private
|
184
|
-
|
185
|
-
def loaded_body
|
186
|
-
case test_case.expected_content_type
|
187
|
-
when %r{json}
|
188
|
-
raise "Body empty while expected" if response.body.to_s.empty?
|
189
|
-
@loaded_body ||= ::JSON.parse(response.body)
|
190
|
-
else
|
191
|
-
response.body.to_s
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def dressed_body
|
196
|
-
@dressed_body ||= case test_case.expected_content_type
|
197
|
-
when %r{json}
|
198
|
-
schema = is_expected_success? ? service.output_schema : service.error_schema
|
199
|
-
begin
|
200
|
-
schema.dress(loaded_body)
|
201
|
-
rescue Finitio::TypeError => ex
|
202
|
-
ex
|
203
|
-
end
|
204
|
-
else
|
205
|
-
loaded_body
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
end # class Invocation
|
210
|
-
end # class Service
|
211
|
-
end # class Resource
|
212
|
-
end # module Webspicy
|
@@ -1,132 +0,0 @@
|
|
1
|
-
module Webspicy
|
2
|
-
class Resource
|
3
|
-
class Service
|
4
|
-
class TestCase
|
5
|
-
|
6
|
-
def initialize(raw)
|
7
|
-
@raw = raw
|
8
|
-
@counterexample = nil
|
9
|
-
end
|
10
|
-
attr_reader :service
|
11
|
-
attr_reader :counterexample
|
12
|
-
|
13
|
-
def bind(service, counterexample)
|
14
|
-
@service = service
|
15
|
-
@counterexample = counterexample
|
16
|
-
self
|
17
|
-
end
|
18
|
-
|
19
|
-
def counterexample?
|
20
|
-
!!@counterexample
|
21
|
-
end
|
22
|
-
|
23
|
-
def resource
|
24
|
-
service.resource
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.info(raw)
|
28
|
-
new(raw)
|
29
|
-
end
|
30
|
-
|
31
|
-
def description
|
32
|
-
@raw[:description]
|
33
|
-
end
|
34
|
-
|
35
|
-
def seeds
|
36
|
-
@raw[:seeds]
|
37
|
-
end
|
38
|
-
|
39
|
-
def headers
|
40
|
-
@raw[:headers] ||= {}
|
41
|
-
end
|
42
|
-
|
43
|
-
def metadata
|
44
|
-
@raw[:metadata] ||= {}
|
45
|
-
end
|
46
|
-
|
47
|
-
def tags
|
48
|
-
@raw[:tags] ||= []
|
49
|
-
end
|
50
|
-
|
51
|
-
def dress_params
|
52
|
-
@raw.fetch(:dress_params){ true }
|
53
|
-
end
|
54
|
-
alias :dress_params? :dress_params
|
55
|
-
|
56
|
-
def params
|
57
|
-
@raw[:params] || {}
|
58
|
-
end
|
59
|
-
|
60
|
-
def body
|
61
|
-
@raw[:body]
|
62
|
-
end
|
63
|
-
|
64
|
-
def file_upload
|
65
|
-
@raw[:file_upload]
|
66
|
-
end
|
67
|
-
|
68
|
-
def located_file_upload
|
69
|
-
file_upload ? file_upload.locate(resource) : nil
|
70
|
-
end
|
71
|
-
|
72
|
-
def expected
|
73
|
-
@raw[:expected] || {}
|
74
|
-
end
|
75
|
-
|
76
|
-
def expected_content_type
|
77
|
-
expected.fetch(:content_type){ 'application/json' }
|
78
|
-
end
|
79
|
-
|
80
|
-
def expected_status
|
81
|
-
expected[:status]
|
82
|
-
end
|
83
|
-
|
84
|
-
def is_expected_status?(status)
|
85
|
-
expected_status === status
|
86
|
-
end
|
87
|
-
|
88
|
-
def expected_error
|
89
|
-
expected[:error]
|
90
|
-
end
|
91
|
-
|
92
|
-
def has_expected_error?
|
93
|
-
!expected_error.nil?
|
94
|
-
end
|
95
|
-
|
96
|
-
def expected_headers
|
97
|
-
expected[:headers] || {}
|
98
|
-
end
|
99
|
-
|
100
|
-
def has_expected_headers?
|
101
|
-
!expected_headers.empty?
|
102
|
-
end
|
103
|
-
|
104
|
-
def assert
|
105
|
-
@raw[:assert] || []
|
106
|
-
end
|
107
|
-
|
108
|
-
def has_assertions?
|
109
|
-
!assert.empty?
|
110
|
-
end
|
111
|
-
|
112
|
-
def to_info
|
113
|
-
@raw
|
114
|
-
end
|
115
|
-
|
116
|
-
def instrument(client)
|
117
|
-
service.preconditions.each do |pre|
|
118
|
-
pre.instrument(self, client)
|
119
|
-
end
|
120
|
-
service.postconditions.each do |post|
|
121
|
-
post.instrument(self, client) if post.respond_to?(:instrument)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def to_s
|
126
|
-
description
|
127
|
-
end
|
128
|
-
|
129
|
-
end # class TestCase
|
130
|
-
end # class Service
|
131
|
-
end # class Resource
|
132
|
-
end # module Webspicy
|
data/lib/webspicy/scope.rb
DELETED
@@ -1,160 +0,0 @@
|
|
1
|
-
module Webspicy
|
2
|
-
class Scope
|
3
|
-
|
4
|
-
def initialize(config)
|
5
|
-
@config = config
|
6
|
-
end
|
7
|
-
attr_reader :config
|
8
|
-
|
9
|
-
def preconditions
|
10
|
-
config.preconditions
|
11
|
-
end
|
12
|
-
|
13
|
-
def postconditions
|
14
|
-
config.postconditions
|
15
|
-
end
|
16
|
-
|
17
|
-
###
|
18
|
-
### Eachers -- Allow navigating the web service definitions
|
19
|
-
###
|
20
|
-
|
21
|
-
# Yields each resource file in the current scope
|
22
|
-
def each_resource_file(&bl)
|
23
|
-
return enum_for(:each_resource_file) unless block_given?
|
24
|
-
_each_resource_file(config, &bl)
|
25
|
-
end
|
26
|
-
|
27
|
-
# Recursive implementation of `each_resource_file` for each
|
28
|
-
# folder in the configuration.
|
29
|
-
def _each_resource_file(config)
|
30
|
-
folder = config.folder
|
31
|
-
folder.glob("**/*.yml").select(&to_filter_proc(config.file_filter)).each do |file|
|
32
|
-
yield file, folder
|
33
|
-
end
|
34
|
-
end
|
35
|
-
private :_each_resource_file
|
36
|
-
|
37
|
-
# Yields each resource in the current scope in turn.
|
38
|
-
def each_resource(&bl)
|
39
|
-
return enum_for(:each_resource) unless block_given?
|
40
|
-
each_resource_file do |file, folder|
|
41
|
-
yield Webspicy.resource(file.load, file, self)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def each_service(resource, &bl)
|
46
|
-
resource.services.select(&to_filter_proc(config.service_filter)).each(&bl)
|
47
|
-
end
|
48
|
-
|
49
|
-
def each_example(service, &bl)
|
50
|
-
service.examples
|
51
|
-
.map{|e| expand_example(service, e) }
|
52
|
-
.select(&to_filter_proc(config.test_case_filter))
|
53
|
-
.each(&bl) if config.run_examples?
|
54
|
-
end
|
55
|
-
|
56
|
-
def each_counterexamples(service, &bl)
|
57
|
-
service.counterexamples
|
58
|
-
.map{|e| expand_example(service, e) }
|
59
|
-
.select(&to_filter_proc(config.test_case_filter))
|
60
|
-
.each(&bl) if config.run_counterexamples?
|
61
|
-
end
|
62
|
-
|
63
|
-
def each_generated_counterexamples(service, &bl)
|
64
|
-
Webspicy.with_scope(self) do
|
65
|
-
service.generated_counterexamples
|
66
|
-
.map{|e| expand_example(service, e) }
|
67
|
-
.select(&to_filter_proc(config.test_case_filter))
|
68
|
-
.each(&bl) if config.run_counterexamples?
|
69
|
-
end if config.run_counterexamples?
|
70
|
-
end
|
71
|
-
|
72
|
-
def each_testcase(service, &bl)
|
73
|
-
each_example(service, &bl)
|
74
|
-
each_counterexamples(service, &bl)
|
75
|
-
each_generated_counterexamples(service, &bl)
|
76
|
-
end
|
77
|
-
|
78
|
-
###
|
79
|
-
### Schemas -- For parsing input and output data schemas found in
|
80
|
-
### web service definitions
|
81
|
-
###
|
82
|
-
|
83
|
-
# Parses a Finitio schema based on the data system.
|
84
|
-
def parse_schema(fio)
|
85
|
-
data_system.parse(fio)
|
86
|
-
end
|
87
|
-
|
88
|
-
# Returns the Data system to use for parsing schemas
|
89
|
-
def data_system
|
90
|
-
@data_system ||= config.data_system
|
91
|
-
end
|
92
|
-
|
93
|
-
|
94
|
-
###
|
95
|
-
### Service invocation: abstract the configuration about what client is
|
96
|
-
### used and how to instantiate it
|
97
|
-
###
|
98
|
-
|
99
|
-
# Returns an instance of the client to use to invoke web services
|
100
|
-
def get_client
|
101
|
-
config.client.new(self)
|
102
|
-
end
|
103
|
-
|
104
|
-
# Convert an instantiated URL found in a webservice definition
|
105
|
-
# to a real URL, using the configuration host.
|
106
|
-
#
|
107
|
-
# When no host resolved on the configuration and the url is not
|
108
|
-
# already an absolute URL, yields the block if given, or raise
|
109
|
-
# an exception.
|
110
|
-
def to_real_url(url, test_case = nil, &bl)
|
111
|
-
case config.host
|
112
|
-
when Proc
|
113
|
-
config.host.call(url, test_case)
|
114
|
-
when String
|
115
|
-
url =~ /^http/ ? url : "#{config.host}#{url}"
|
116
|
-
else
|
117
|
-
return url if url =~ /^http/
|
118
|
-
return yield(url) if block_given?
|
119
|
-
raise "Unable to resolve `#{url}` : no host resolver provided\nSee `Configuration#host="
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
###
|
124
|
-
### Private methods
|
125
|
-
###
|
126
|
-
|
127
|
-
private
|
128
|
-
|
129
|
-
def expand_example(service, example)
|
130
|
-
return example unless service.default_example
|
131
|
-
h1 = service.default_example.to_info
|
132
|
-
h2 = example.to_info
|
133
|
-
ex = Resource::Service::TestCase.new(merge_maps(h1, h2))
|
134
|
-
ex.bind(service, example.counterexample?)
|
135
|
-
end
|
136
|
-
|
137
|
-
def merge_maps(h1, h2)
|
138
|
-
h1.merge(h2) do |k,v1,v2|
|
139
|
-
case v1
|
140
|
-
when Hash then merge_maps(v1, v2)
|
141
|
-
when Array then v1 + v2
|
142
|
-
else v2
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
# Returns a proc that implements file_filter strategy according to the
|
148
|
-
# type of filter installed
|
149
|
-
def to_filter_proc(filter)
|
150
|
-
case ff = filter
|
151
|
-
when NilClass then ->(f){ true }
|
152
|
-
when Proc then ff
|
153
|
-
when Regexp then ->(f){ ff =~ f.to_s }
|
154
|
-
else
|
155
|
-
->(f){ ff === f }
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
end
|
160
|
-
end
|