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
@@ -0,0 +1,65 @@
|
|
1
|
+
module Webspicy
|
2
|
+
class Tester
|
3
|
+
class Client
|
4
|
+
module Support
|
5
|
+
include Webspicy::Support::Colorize
|
6
|
+
|
7
|
+
NONE = Object.new
|
8
|
+
|
9
|
+
def querystring_params(params)
|
10
|
+
Hash[params.each_pair.map{|k,v| [k.to_s,v.to_s] }]
|
11
|
+
end
|
12
|
+
|
13
|
+
def info_request(kind, url, params, headers, body)
|
14
|
+
Webspicy.info(colorize_highlight("~> #{kind} #{url}"))
|
15
|
+
debug(" Req params", json_pretty(params)) if params
|
16
|
+
debug(" Req headers", json_pretty(headers)) if headers
|
17
|
+
debug(" Req body", request_body_to_s(body)) if body
|
18
|
+
end
|
19
|
+
|
20
|
+
def debug_response(response)
|
21
|
+
debug(colorize_highlight("."))
|
22
|
+
debug(" Res status", status_to_s(@last_response.status))
|
23
|
+
debug(" Res headers", json_pretty(last_response.headers.to_h))
|
24
|
+
debug(" Res body", response_body_to_s(last_response))
|
25
|
+
Webspicy.debug("")
|
26
|
+
end
|
27
|
+
|
28
|
+
def debug(what, value = NONE)
|
29
|
+
return Webspicy.debug(" #{what}") if value == NONE
|
30
|
+
Webspicy.debug(" #{what}: " + value_to_s(value))
|
31
|
+
end
|
32
|
+
|
33
|
+
def request_body_to_s(body)
|
34
|
+
body = body.to_info if body.is_a?(Webspicy::FileUpload)
|
35
|
+
json_pretty(body)
|
36
|
+
end
|
37
|
+
|
38
|
+
def response_body_to_s(response)
|
39
|
+
case response.content_type.to_s
|
40
|
+
when /json/
|
41
|
+
json_pretty(JSON.load(response.body))
|
42
|
+
else
|
43
|
+
response.body.to_s
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def value_to_s(value)
|
48
|
+
value.to_s.gsub(/\n/, "\n ")
|
49
|
+
end
|
50
|
+
|
51
|
+
def status_to_s(status)
|
52
|
+
case status
|
53
|
+
when 0 ... 400 then colorize_success(status.to_s)
|
54
|
+
else colorize_error(status.to_s)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def json_pretty(s)
|
59
|
+
JSON.pretty_generate(s)
|
60
|
+
end
|
61
|
+
|
62
|
+
end # module Support
|
63
|
+
end # class Client
|
64
|
+
end # class Tester
|
65
|
+
end # module Webspicy
|
@@ -0,0 +1,218 @@
|
|
1
|
+
module Webspicy
|
2
|
+
class Tester
|
3
|
+
class Invocation
|
4
|
+
|
5
|
+
def initialize(test_case, response, client)
|
6
|
+
@test_case = test_case
|
7
|
+
@response = response
|
8
|
+
@client = client
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :test_case, :response, :client
|
12
|
+
|
13
|
+
def service
|
14
|
+
test_case.service
|
15
|
+
end
|
16
|
+
|
17
|
+
def rspec_assert!(rspec)
|
18
|
+
RSpecAsserter.new(rspec, self).assert!
|
19
|
+
end
|
20
|
+
|
21
|
+
def errors
|
22
|
+
@errors ||= begin
|
23
|
+
errs = [
|
24
|
+
[:expected_status_unmet, true],
|
25
|
+
[:expected_content_type_unmet, !test_case.is_expected_status?(204)],
|
26
|
+
[:expected_headers_unmet, test_case.has_expected_headers?],
|
27
|
+
[:expected_schema_unmet, !test_case.is_expected_status?(204)],
|
28
|
+
[:assertions_unmet, test_case.has_assertions?],
|
29
|
+
[:postconditions_unmet, test_case.service.has_postconditions? && !test_case.counterexample?],
|
30
|
+
[:expected_error_unmet, test_case.has_expected_error?]
|
31
|
+
].map do |(expectation,only_if)|
|
32
|
+
next unless only_if
|
33
|
+
begin
|
34
|
+
self.send(expectation)
|
35
|
+
rescue => ex
|
36
|
+
ex.message
|
37
|
+
end
|
38
|
+
end
|
39
|
+
errs.compact
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def has_error?
|
44
|
+
!errors.empty?
|
45
|
+
end
|
46
|
+
|
47
|
+
### Getters on response
|
48
|
+
|
49
|
+
def response_code
|
50
|
+
code = response.status
|
51
|
+
code = code.code unless code.is_a?(Integer)
|
52
|
+
code
|
53
|
+
end
|
54
|
+
|
55
|
+
### Query methods
|
56
|
+
|
57
|
+
def done?
|
58
|
+
!response.nil?
|
59
|
+
end
|
60
|
+
|
61
|
+
def is_expected_success?
|
62
|
+
test_case.expected_status.to_i >= 200 && test_case.expected_status.to_i < 300
|
63
|
+
end
|
64
|
+
|
65
|
+
def is_success?
|
66
|
+
response_code >= 200 && response_code < 300
|
67
|
+
end
|
68
|
+
|
69
|
+
def is_empty_response?
|
70
|
+
response_code == 204
|
71
|
+
end
|
72
|
+
|
73
|
+
def is_redirect?
|
74
|
+
response_code >= 300 && response_code < 400
|
75
|
+
end
|
76
|
+
|
77
|
+
### Check of HTTP status
|
78
|
+
|
79
|
+
def expected_status_unmet
|
80
|
+
expected = test_case.expected_status
|
81
|
+
got = response.status
|
82
|
+
expected === got ? nil : "[status] #{expected} !== #{got}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def meets_expected_status?
|
86
|
+
expected_status_unmet.nil?
|
87
|
+
end
|
88
|
+
|
89
|
+
### Check of the expected output type
|
90
|
+
|
91
|
+
def expected_content_type_unmet
|
92
|
+
ect = test_case.expected_content_type
|
93
|
+
return nil unless ect
|
94
|
+
got = response.content_type
|
95
|
+
got = got.mime_type if got.respond_to?(:mime_type)
|
96
|
+
if ect.nil?
|
97
|
+
got.nil? ? nil : "[content type] #{ect} != #{got}"
|
98
|
+
else
|
99
|
+
got.to_s.start_with?(ect.to_s) ? nil : "[content type] #{ect} != #{got}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def meets_expected_content_type?
|
104
|
+
expected_content_type_unmet.nil?
|
105
|
+
end
|
106
|
+
|
107
|
+
### Check of output schema
|
108
|
+
|
109
|
+
def expected_schema_unmet
|
110
|
+
if is_empty_response?
|
111
|
+
body = response.body.to_s.strip
|
112
|
+
body.empty? ? nil : "[body] empty vs. #{body}"
|
113
|
+
elsif is_redirect?
|
114
|
+
else
|
115
|
+
case dressed_body
|
116
|
+
when Finitio::TypeError
|
117
|
+
rc = dressed_body.root_cause
|
118
|
+
"#{rc.message} (#{rc.location ? rc.location : 'unknown location'})"
|
119
|
+
when StandardError
|
120
|
+
dressed_body.message
|
121
|
+
else nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def meets_expected_schema?
|
127
|
+
expected_schema_unmet.nil?
|
128
|
+
end
|
129
|
+
|
130
|
+
### Check of assertions
|
131
|
+
|
132
|
+
def assertions_unmet
|
133
|
+
unmet = []
|
134
|
+
asserter = Tester::Asserter.new(dressed_body)
|
135
|
+
test_case.assert.each do |assert|
|
136
|
+
begin
|
137
|
+
asserter.instance_eval(assert)
|
138
|
+
rescue => ex
|
139
|
+
unmet << ex.message
|
140
|
+
end
|
141
|
+
end
|
142
|
+
unmet.empty? ? nil : unmet.join("\n")
|
143
|
+
end
|
144
|
+
|
145
|
+
def value_equal(exp, got)
|
146
|
+
case exp
|
147
|
+
when Hash
|
148
|
+
exp.all?{|(k,v)|
|
149
|
+
got[k] == v
|
150
|
+
}
|
151
|
+
else
|
152
|
+
exp == got
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
### Check of expected error message
|
157
|
+
|
158
|
+
def expected_error_unmet
|
159
|
+
expected = test_case.expected_error
|
160
|
+
case test_case.expected_content_type
|
161
|
+
when %r{json}
|
162
|
+
got = meets_expected_schema? ? dressed_body[:description] : response.body
|
163
|
+
expected == got ? nil : "[error message] `#{expected}` vs. `#{got}`"
|
164
|
+
else
|
165
|
+
dressed_body.include?(expected) ? nil : "[error message] `#{expected}` not found" unless expected.nil?
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
### Check of expected headers
|
170
|
+
|
171
|
+
def expected_headers_unmet
|
172
|
+
unmet = []
|
173
|
+
expected = test_case.expected_headers
|
174
|
+
expected.each_pair do |k,v|
|
175
|
+
got = response.headers[k]
|
176
|
+
unmet << "[headers] #{v} expected for #{k}, got #{got}" unless (got == v)
|
177
|
+
end
|
178
|
+
unmet.empty? ? nil : unmet.join("\n")
|
179
|
+
end
|
180
|
+
|
181
|
+
### Check of postconditions
|
182
|
+
|
183
|
+
def postconditions_unmet
|
184
|
+
failures = service.postconditions.map{|post|
|
185
|
+
post.check(self)
|
186
|
+
}.compact
|
187
|
+
failures.empty? ? nil : failures.join("\n")
|
188
|
+
end
|
189
|
+
|
190
|
+
def loaded_body
|
191
|
+
case test_case.expected_content_type
|
192
|
+
when %r{json}
|
193
|
+
raise "Body empty while expected" if response.body.to_s.empty?
|
194
|
+
@loaded_body ||= ::JSON.parse(response.body)
|
195
|
+
else
|
196
|
+
response.body.to_s
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def dressed_body
|
201
|
+
@dressed_body ||= case test_case.expected_content_type
|
202
|
+
when %r{json}
|
203
|
+
schema = is_expected_success? ? service.output_schema : service.error_schema
|
204
|
+
begin
|
205
|
+
schema.dress(loaded_body)
|
206
|
+
rescue Finitio::TypeError => ex
|
207
|
+
ex
|
208
|
+
end
|
209
|
+
else
|
210
|
+
loaded_body
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
end # class Invocation
|
215
|
+
end # class Tester
|
216
|
+
end # module Webspicy
|
217
|
+
require_relative 'rspec_matchers'
|
218
|
+
require_relative 'rspec_asserter'
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Webspicy
|
2
|
+
class Tester
|
3
|
+
class RSpecAsserter
|
4
|
+
|
5
|
+
def initialize(rspec, invocation)
|
6
|
+
@rspec = rspec
|
7
|
+
@invocation = invocation
|
8
|
+
end
|
9
|
+
attr_reader :rspec, :invocation
|
10
|
+
|
11
|
+
def response
|
12
|
+
invocation.response
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_case
|
16
|
+
invocation.test_case
|
17
|
+
end
|
18
|
+
|
19
|
+
def service
|
20
|
+
test_case.service
|
21
|
+
end
|
22
|
+
|
23
|
+
def assert!
|
24
|
+
assert_status_met
|
25
|
+
assert_content_type_met
|
26
|
+
assert_expected_headers
|
27
|
+
assert_output_schema_met
|
28
|
+
assert_assertions_met
|
29
|
+
assert_postconditions_met
|
30
|
+
|
31
|
+
assert_no_other_errors
|
32
|
+
end
|
33
|
+
|
34
|
+
def assert_status_met
|
35
|
+
got = response.status
|
36
|
+
expected = test_case.expected_status
|
37
|
+
rspec.expect(got).to rspec.match_response_status(expected)
|
38
|
+
end
|
39
|
+
|
40
|
+
def assert_content_type_met
|
41
|
+
return if test_case.is_expected_status?(204)
|
42
|
+
return unless ect = test_case.expected_content_type
|
43
|
+
got = response.content_type
|
44
|
+
got = got.mime_type if got.respond_to?(:mime_type)
|
45
|
+
if ect.nil?
|
46
|
+
rspec.expect(ect).to rspec.have_no_response_type
|
47
|
+
else
|
48
|
+
rspec.expect(got).to rspec.match_content_type(ect)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def assert_expected_headers
|
53
|
+
return unless test_case.has_expected_headers?
|
54
|
+
test_case.expected_headers.each_pair do |k,v|
|
55
|
+
got = response.headers[k]
|
56
|
+
if got.nil?
|
57
|
+
rspec.expect(got).to rspec.be_in_response_headers(k)
|
58
|
+
else
|
59
|
+
rspec.expect(got).to rspec.match_response_header(k, v)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def assert_output_schema_met
|
65
|
+
return if test_case.is_expected_status?(204)
|
66
|
+
return if invocation.is_redirect?
|
67
|
+
if invocation.is_empty_response?
|
68
|
+
body = response.body.to_s.strip
|
69
|
+
rspec.expect(body).to rspec.be_an_empty_response_body
|
70
|
+
else
|
71
|
+
b = invocation.dressed_body
|
72
|
+
if invocation.is_expected_success?
|
73
|
+
rspec.expect(b).to rspec.meet_output_schema
|
74
|
+
else
|
75
|
+
rspec.expect(b).to rspec.meet_error_schema
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def assert_assertions_met
|
81
|
+
return unless test_case.has_assertions?
|
82
|
+
asserter = Tester::Asserter.new(invocation.dressed_body)
|
83
|
+
test_case.assert.each do |assert|
|
84
|
+
begin
|
85
|
+
asserter.instance_eval(assert)
|
86
|
+
rescue => ex
|
87
|
+
rspec.expect(ex).to rspec.meet_assertion(assert)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def assert_postconditions_met
|
93
|
+
return unless service.has_postconditions?
|
94
|
+
return if test_case.counterexample?
|
95
|
+
service.postconditions.each do |post|
|
96
|
+
msg = post.check(invocation)
|
97
|
+
rspec.expect(msg).to rspec.meet_postcondition(post)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def assert_no_other_errors
|
102
|
+
errors = invocation.errors
|
103
|
+
rspec.expect(errors).to rspec.be_an_empty_errors_array
|
104
|
+
end
|
105
|
+
|
106
|
+
end # class RSpecAsserter
|
107
|
+
end # class Tester
|
108
|
+
end # module Webspicy
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'rspec/expectations'
|
2
|
+
|
3
|
+
RSpec::Matchers.define :match_response_status do |expected|
|
4
|
+
match do |actual|
|
5
|
+
expected === actual
|
6
|
+
end
|
7
|
+
failure_message_for_should do |actual|
|
8
|
+
"expected response status #{actual} to be #{expected}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
RSpec::Matchers.define :have_no_response_type do
|
13
|
+
match do |actual|
|
14
|
+
actual.nil?
|
15
|
+
end
|
16
|
+
failure_message_for_should do |actual|
|
17
|
+
"expected Content-Type not to be present"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
RSpec::Matchers.define :match_content_type do |expected|
|
22
|
+
match do |actual|
|
23
|
+
actual.to_s.start_with?(expected.to_s)
|
24
|
+
end
|
25
|
+
failure_message_for_should do |actual|
|
26
|
+
"expected Content-Type to be `#{expected}`, got `#{actual}`"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
RSpec::Matchers.define :be_in_response_headers do |header_name|
|
31
|
+
match do |actual|
|
32
|
+
!actual.nil?
|
33
|
+
end
|
34
|
+
failure_message_for_should do |actual|
|
35
|
+
"expected response header `#{header_name}` to be set"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
RSpec::Matchers.define :match_response_header do |header_name, expected|
|
40
|
+
match do |actual|
|
41
|
+
expected == actual
|
42
|
+
end
|
43
|
+
failure_message_for_should do |actual|
|
44
|
+
"expected response header `#{header_name}` to be `#{expected}`, got `#{actual}`"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
RSpec::Matchers.define :be_an_empty_response_body do
|
49
|
+
match do |actual|
|
50
|
+
actual.empty?
|
51
|
+
end
|
52
|
+
failure_message_for_should do |actual|
|
53
|
+
"expected response body to be empty, started with `#{actual[0..20]}`"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
RSpec::Matchers.define :meet_output_schema do
|
58
|
+
match do |actual|
|
59
|
+
!actual.is_a?(Exception)
|
60
|
+
end
|
61
|
+
failure_message_for_should do |actual|
|
62
|
+
"expected response body to meet output schema, got following error:\n" + \
|
63
|
+
" #{actual.message}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
RSpec::Matchers.define :meet_error_schema do
|
68
|
+
match do |actual|
|
69
|
+
!actual.is_a?(Exception)
|
70
|
+
end
|
71
|
+
failure_message_for_should do |actual|
|
72
|
+
"expected response body to meet error schema, got following error:\n" + \
|
73
|
+
" #{actual.message}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
RSpec::Matchers.define :meet_assertion do |assert|
|
78
|
+
match do |actual|
|
79
|
+
actual.nil?
|
80
|
+
end
|
81
|
+
failure_message_for_should do |actual|
|
82
|
+
"expected assertion `#{assert}` to be met, got following error:\n" + \
|
83
|
+
" #{actual.message}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
RSpec::Matchers.define :meet_postcondition do |post|
|
88
|
+
match do |actual|
|
89
|
+
actual.nil?
|
90
|
+
end
|
91
|
+
failure_message_for_should do |actual|
|
92
|
+
"expected postcondition `#{post.class.name}` to be met, got following error:\n" + \
|
93
|
+
" #{actual}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
RSpec::Matchers.define :be_an_empty_errors_array do
|
98
|
+
match do |actual|
|
99
|
+
actual.empty?
|
100
|
+
end
|
101
|
+
failure_message_for_should do |actual|
|
102
|
+
"expected no webspicy error, got the following ones:\n" + actual.map{|a| " #{a}" }.join("\n")
|
103
|
+
end
|
104
|
+
end
|