webspicy 0.15.7 → 0.16.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7cbfb644d2ae34f2e2e87aa2d69b50b762299770b9c0109fbc5281fdd3b80d22
|
4
|
+
data.tar.gz: 6bf17b7423bb6ff33b53d8f12dc761094e613961487c146c66a87ce84b792bc7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 403ddeb22ffccd059d8450a6290f7f190d97bc45ef12a04a43a97059d733085ce4fe2865f31a5452d43c18e4244a53129ac280cd37db09b8a6ce50e76506f8f6
|
7
|
+
data.tar.gz: '095210fda4e1b4e903c1803a2cd75420a905894b06d4403e8f1019df0c43eeec10eb3952b8d06397bdb0d8a753361c01f1577f85f09ca34258386020276dcdaa'
|
data/README.md
CHANGED
@@ -1,46 +1,93 @@
|
|
1
1
|
# Webspicy
|
2
2
|
|
3
|
-
A
|
4
|
-
|
3
|
+
A specification and test framework for web services seen as black-box software
|
4
|
+
operations. Webspicy yields a better test coverage for a smaller testing effort,
|
5
|
+
because software quality matters.
|
6
|
+
|
7
|
+
See webspicy in action and make the tutorial on https://yourbackendisbroken.dev
|
5
8
|
|
6
9
|
## Features
|
7
10
|
|
8
|
-
* Declarative
|
11
|
+
* Declarative specification of HTTP web services + their tests
|
12
|
+
|
13
|
+
* Framework/language agnostic: `webspicy` is written in Ruby, but can be used
|
14
|
+
to test web services for backends written in any language / framework.
|
15
|
+
|
16
|
+
* Black box testing: `webspicy` focuses on web services seen as blackboxes. It
|
17
|
+
has no knowledge of the implementation, and focuses on HTTP and input/output
|
18
|
+
data instead. Investing in such testing makes those tests more stable and
|
19
|
+
your API design better.
|
9
20
|
|
10
|
-
*
|
11
|
-
|
21
|
+
* Formal and human-friendly data schema with strong data matching semantics,
|
22
|
+
thanks to finitio.io
|
12
23
|
|
13
|
-
*
|
14
|
-
no knowledge of the implementation, and focuses on HTTP and input/output data
|
15
|
-
instead. Investing in such testing makes those tests more stable and your API
|
16
|
-
better.
|
24
|
+
* Test instrumentation and generation, based on PRE & POST contracts.
|
17
25
|
|
18
|
-
*
|
19
|
-
|
26
|
+
* Extra goodness for Rubyists: being written in ruby, `webspicy` also supports
|
27
|
+
testing Rack applications directly (through rack/test), which boosts the
|
28
|
+
test suite.
|
20
29
|
|
21
|
-
* Extra
|
22
|
-
|
30
|
+
* Extra goodies: when a specification is written, it can also be used for
|
31
|
+
mocking the API, generating an openapi file, etc.
|
23
32
|
|
24
|
-
## Getting started
|
33
|
+
## Getting started with the commandline
|
25
34
|
|
26
|
-
|
27
|
-
with GET and POST restful services tested with the framework. The Rakefile contains
|
28
|
-
the necessary tasks to run those tests.
|
35
|
+
To install webspicy on your developer computer, install ruby then:
|
29
36
|
|
30
|
-
|
37
|
+
```
|
38
|
+
gem install webspicy
|
39
|
+
```
|
31
40
|
|
32
|
-
|
41
|
+
Then execute webspicy help to see the options.
|
33
42
|
|
34
43
|
```
|
35
44
|
webspicy --help
|
36
|
-
webspicy path/to/your/config.rb
|
37
45
|
```
|
38
46
|
|
39
|
-
## Using the docker image
|
47
|
+
## Using the docker image(s)
|
48
|
+
|
49
|
+
If you just want to play with the commandline tool without having to
|
50
|
+
install ruby & webspicy, you can use the docker image we provide for
|
51
|
+
the commandline:
|
52
|
+
|
53
|
+
```
|
54
|
+
docker run enspirit/webspicy --help
|
55
|
+
```
|
56
|
+
|
57
|
+
If you have a specification & test suite somewhere, an easy way to run the
|
58
|
+
whole suite (or integrate it in your continuous integration pipeline) is
|
59
|
+
to use our `:tester` docker image. Just mount your test suite as a volume
|
60
|
+
in `/home/app` and you are good to go:
|
40
61
|
|
41
|
-
|
42
|
-
|
62
|
+
```
|
63
|
+
docker run -v path/to/tests:/formalspec enspirit/webspicy:tester
|
64
|
+
```
|
65
|
+
|
66
|
+
If your plan is to test a backend that runs on your own machine (vs.
|
67
|
+
publicly on the Internet or inside the default docker network),
|
68
|
+
you will need to add some networking option, as shown below. Please
|
69
|
+
refer to Docker documentation.
|
43
70
|
|
44
71
|
```
|
45
|
-
docker run
|
72
|
+
docker run -v path/to/tests:/formalspec --network=host enspirit/webspicy:tester
|
46
73
|
```
|
74
|
+
|
75
|
+
## Contributing
|
76
|
+
|
77
|
+
Please use github issues for questions and bugs, and pull requests for
|
78
|
+
submitting improvement proposals and new features.
|
79
|
+
|
80
|
+
## Contributors
|
81
|
+
|
82
|
+
* Bernard Lambeau (blambeau)
|
83
|
+
* Louis Lambeau (llambeau)
|
84
|
+
* Yoann Guyot (ygu)
|
85
|
+
* Felix Holmgren (@felixyz)
|
86
|
+
|
87
|
+
Enspirit (https://enspirit.be) and Klaro App (https://klaro.cards) are
|
88
|
+
both actively using, contributing and funding work on this library.
|
89
|
+
Please contact Bernard Lambeau for any question.
|
90
|
+
|
91
|
+
## Licence
|
92
|
+
|
93
|
+
Webspicy is distributed under a MIT Licence, by Enspirit SRL.
|
data/bin/webspicy
CHANGED
@@ -1,15 +1,25 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
#/
|
3
|
-
#/
|
4
|
-
#/
|
2
|
+
#/
|
3
|
+
#/ Document & test web services as black-box operations.
|
4
|
+
#/ (c) Enspirit SRL. Distributed under MIT licence.
|
5
|
+
#/
|
6
|
+
#/ Usage: webspicy [options] URL # run default test againt url
|
7
|
+
#/ Usage: webspicy [options] path/to/config.rb # run whole test suite
|
8
|
+
#/ Usage: webspicy [options] path/to/spec.yml # run a single test
|
9
|
+
#/
|
10
|
+
#/ Options:
|
11
|
+
#/ -h, --help Show this help message
|
12
|
+
#/ -v, --version Show webspicy version
|
13
|
+
#/ --debug Same as LOG_LEVEL=DEBUG, takes precedence
|
5
14
|
#/
|
6
15
|
#/ Recognized env vars:
|
7
|
-
#/ - ROBUST=no
|
16
|
+
#/ - ROBUST=no|only|generated execute no counterexamples (only them, only generated ones)
|
8
17
|
#/ - LOG_LEVEL=INFO|DEBUG|... set log level to the appropriate level
|
9
18
|
#/ - RESOURCE=... restrict to .yml test files matching the pattern
|
10
|
-
#/ - METHOD=GET|POST|DELETE... execute only tests matching the verb
|
19
|
+
#/ - METHOD=GET|POST|DELETE... execute only tests matching the HTTP verb
|
11
20
|
#/ - TAG=... execute only tests matching the given tag
|
12
21
|
#/ - FAILFAST=yes|no stop executing tests on first failure
|
22
|
+
#/
|
13
23
|
require 'webspicy'
|
14
24
|
require 'webspicy/tester'
|
15
25
|
require 'optparse'
|
@@ -20,19 +30,25 @@ def showhelp
|
|
20
30
|
end
|
21
31
|
|
22
32
|
ARGV.options do |opts|
|
23
|
-
opts.on_tail("-h", "--help"){
|
33
|
+
opts.on_tail("-h", "--help"){
|
34
|
+
showhelp
|
35
|
+
}
|
36
|
+
opts.on("-v", "--version"){
|
37
|
+
puts "webspicy v#{Webspicy::VERSION}, (c) Enspirit SRL"
|
38
|
+
exit(0)
|
39
|
+
}
|
40
|
+
opts.on("--debug") {
|
41
|
+
ENV['LOG_LEVEL'] = 'DEBUG'
|
42
|
+
Webspicy::LOGGER.level = Logger.const_get(ENV['LOG_LEVEL'])
|
43
|
+
}
|
24
44
|
opts.parse!
|
25
45
|
end
|
26
46
|
|
27
47
|
if ARGV.size != 1
|
28
48
|
showhelp
|
29
49
|
exit(-1)
|
30
|
-
elsif (p = Path(ARGV.first)).exists?
|
31
|
-
config = Webspicy::Configuration.dress(p)
|
32
|
-
res = Webspicy::Tester.new(config).call
|
33
|
-
abort("Some tests failed") unless res == 0
|
34
|
-
else
|
35
|
-
puts "No such file or directory `#{ARGV.first}`"
|
36
|
-
showhelp
|
37
|
-
exit(-1)
|
38
50
|
end
|
51
|
+
|
52
|
+
config = Webspicy::Configuration.dress(ARGV[0])
|
53
|
+
res = Webspicy::Tester.new(config).call
|
54
|
+
abort("Some tests failed") unless res == 0
|
data/examples/restful/Gemfile
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ../..
|
3
3
|
specs:
|
4
|
-
webspicy (0.
|
5
|
-
|
4
|
+
webspicy (0.16.3)
|
5
|
+
colorize (~> 0.8.1)
|
6
|
+
finitio (~> 0.9.0)
|
6
7
|
http (>= 2)
|
7
8
|
mustermann (~> 1.0)
|
8
9
|
mustermann-contrib
|
9
|
-
|
10
|
+
openapi3_parser (~> 0.8.2)
|
11
|
+
path (~> 2.0)
|
10
12
|
rack-robustness (~> 1.1, >= 1.1.0)
|
11
13
|
rack-test (~> 0.6.3)
|
12
14
|
rspec (~> 3.7)
|
@@ -18,68 +20,86 @@ GEM
|
|
18
20
|
addressable (2.7.0)
|
19
21
|
public_suffix (>= 2.0.2, < 5.0)
|
20
22
|
citrus (3.0.2)
|
21
|
-
|
23
|
+
colorize (0.8.1)
|
24
|
+
commonmarker (0.21.0)
|
25
|
+
ruby-enum (~> 0.5)
|
26
|
+
concurrent-ruby (1.1.7)
|
27
|
+
diff-lcs (1.4.4)
|
22
28
|
domain_name (0.5.20190701)
|
23
29
|
unf (>= 0.0.5, < 1.0.0)
|
24
|
-
|
30
|
+
ffi (1.13.1)
|
31
|
+
ffi-compiler (1.0.1)
|
32
|
+
ffi (>= 1.0.0)
|
33
|
+
rake
|
34
|
+
finitio (0.9.0)
|
25
35
|
citrus (>= 2.4, < 4.0)
|
26
36
|
hansi (0.2.0)
|
27
|
-
http (
|
37
|
+
http (4.4.1)
|
28
38
|
addressable (~> 2.3)
|
29
39
|
http-cookie (~> 1.0)
|
30
|
-
http-form_data (~>
|
31
|
-
|
40
|
+
http-form_data (~> 2.2)
|
41
|
+
http-parser (~> 1.2.0)
|
32
42
|
http-cookie (1.0.3)
|
33
43
|
domain_name (~> 0.5)
|
34
|
-
http-form_data (
|
35
|
-
|
44
|
+
http-form_data (2.3.0)
|
45
|
+
http-parser (1.2.2)
|
46
|
+
ffi-compiler
|
47
|
+
i18n (1.8.5)
|
48
|
+
concurrent-ruby (~> 1.0)
|
36
49
|
mustermann (1.1.1)
|
37
50
|
ruby2_keywords (~> 0.0.1)
|
38
51
|
mustermann-contrib (1.1.1)
|
39
52
|
hansi (~> 0.2.0)
|
40
53
|
mustermann (= 1.1.1)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
54
|
+
openapi3_parser (0.8.2)
|
55
|
+
commonmarker (~> 0.17)
|
56
|
+
psych (~> 3.1)
|
57
|
+
path (2.0.1)
|
58
|
+
psych (3.2.1)
|
59
|
+
public_suffix (4.0.6)
|
60
|
+
rack (2.2.3)
|
61
|
+
rack-protection (2.1.0)
|
45
62
|
rack
|
46
63
|
rack-robustness (1.1.0)
|
47
64
|
rack-test (0.6.3)
|
48
65
|
rack (>= 1.0)
|
49
|
-
rake (
|
50
|
-
rspec (3.
|
51
|
-
rspec-core (~> 3.
|
52
|
-
rspec-expectations (~> 3.
|
53
|
-
rspec-mocks (~> 3.
|
54
|
-
rspec-core (3.
|
55
|
-
rspec-support (~> 3.
|
56
|
-
rspec-expectations (3.
|
66
|
+
rake (12.3.3)
|
67
|
+
rspec (3.10.0)
|
68
|
+
rspec-core (~> 3.10.0)
|
69
|
+
rspec-expectations (~> 3.10.0)
|
70
|
+
rspec-mocks (~> 3.10.0)
|
71
|
+
rspec-core (3.10.0)
|
72
|
+
rspec-support (~> 3.10.0)
|
73
|
+
rspec-expectations (3.10.0)
|
57
74
|
diff-lcs (>= 1.2.0, < 2.0)
|
58
|
-
rspec-support (~> 3.
|
59
|
-
rspec-mocks (3.
|
75
|
+
rspec-support (~> 3.10.0)
|
76
|
+
rspec-mocks (3.10.0)
|
60
77
|
diff-lcs (>= 1.2.0, < 2.0)
|
61
|
-
rspec-support (~> 3.
|
62
|
-
rspec-support (3.
|
78
|
+
rspec-support (~> 3.10.0)
|
79
|
+
rspec-support (3.10.0)
|
63
80
|
rspec_junit_formatter (0.4.1)
|
64
81
|
rspec-core (>= 2, < 4, != 2.12.0)
|
82
|
+
ruby-enum (0.8.0)
|
83
|
+
i18n
|
65
84
|
ruby2_keywords (0.0.2)
|
66
|
-
sinatra (2.0
|
85
|
+
sinatra (2.1.0)
|
67
86
|
mustermann (~> 1.0)
|
68
|
-
rack (~> 2.
|
69
|
-
rack-protection (= 2.0
|
87
|
+
rack (~> 2.2)
|
88
|
+
rack-protection (= 2.1.0)
|
70
89
|
tilt (~> 2.0)
|
71
90
|
tilt (2.0.10)
|
72
91
|
unf (0.1.4)
|
73
92
|
unf_ext
|
74
|
-
unf_ext (0.0.7.
|
93
|
+
unf_ext (0.0.7.7)
|
75
94
|
|
76
95
|
PLATFORMS
|
77
96
|
ruby
|
97
|
+
x86_64-darwin-15
|
78
98
|
|
79
99
|
DEPENDENCIES
|
80
|
-
rake (~>
|
81
|
-
sinatra (~> 2
|
100
|
+
rake (~> 12)
|
101
|
+
sinatra (~> 2)
|
82
102
|
webspicy!
|
83
103
|
|
84
104
|
BUNDLED WITH
|
85
|
-
2.
|
105
|
+
2.2.1
|
data/examples/restful/Rakefile
CHANGED
data/examples/restful/app.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'webspicy'
|
1
2
|
require 'sinatra'
|
2
3
|
require 'json'
|
3
4
|
require 'path'
|
@@ -65,6 +66,7 @@ post '/reset' do
|
|
65
66
|
end
|
66
67
|
|
67
68
|
get '/todo/' do
|
69
|
+
raise unless request.env['HTTP_ACCEPT'] == 'application/json'
|
68
70
|
content_type :json
|
69
71
|
settings.todolist.to_json
|
70
72
|
end
|
@@ -94,6 +96,7 @@ post '/todo/', :auth => :user do
|
|
94
96
|
end
|
95
97
|
|
96
98
|
get '/todo/:id' do |id|
|
99
|
+
raise unless request.env['HTTP_ACCEPT'] == 'application/json'
|
97
100
|
content_type :json
|
98
101
|
todo = settings.todolist.find{|todo| todo[:id] == Integer(id) }
|
99
102
|
if todo.nil?
|
@@ -111,7 +114,7 @@ patch '/todo/:id', :auth => :user do |id|
|
|
111
114
|
status 404
|
112
115
|
{error: "No such todo"}.to_json
|
113
116
|
else
|
114
|
-
patch = SCHEMA["TodoPatch"].dress(loaded_body)
|
117
|
+
patch = SCHEMA["TodoPatch"].dress(loaded_body.merge("id" => Integer(id)))
|
115
118
|
patched = todo.merge(patch)
|
116
119
|
settings.todolist = settings.todolist.reject{|todo| todo[:id] == Integer(id) }
|
117
120
|
settings.todolist << patched
|
@@ -4,6 +4,14 @@ def webspicy_config(&bl)
|
|
4
4
|
c.precondition MustBeAuthenticated
|
5
5
|
c.precondition MustBeAnAdmin
|
6
6
|
|
7
|
+
c.precondition Webspicy::Specification::Precondition::GlobalRequestHeaders.new({
|
8
|
+
'Accept' => 'application/json'
|
9
|
+
}){|service| service.method == "GET" }
|
10
|
+
|
11
|
+
c.precondition Webspicy::Specification::Precondition::RobustToInvalidInput.new
|
12
|
+
|
13
|
+
c.postcondition TodoRemoved
|
14
|
+
|
7
15
|
c.instrument do |tc, client|
|
8
16
|
role = tc.metadata[:role]
|
9
17
|
tc.headers['Authorization'] = "Bearer #{role}" if role
|
@@ -30,7 +30,7 @@ class MustBeAuthenticated
|
|
30
30
|
def counterexample(description, role, expected, status = 401)
|
31
31
|
YAML.load <<-YML.gsub(/^\s+[#][ ]/, "")
|
32
32
|
# description: |-
|
33
|
-
# (#{self.class.name})
|
33
|
+
# #{description} (#{self.class.name} PRE)
|
34
34
|
# params:
|
35
35
|
# id: 1
|
36
36
|
# dress_params:
|
@@ -41,7 +41,7 @@ class MustBeAuthenticated
|
|
41
41
|
# content_type: application/json
|
42
42
|
# status: #{status}
|
43
43
|
# assert:
|
44
|
-
# - "pathFD('', error: '#{expected}')"
|
44
|
+
# - "pathFD('', error: '#{expected}')"
|
45
45
|
YML
|
46
46
|
end
|
47
47
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class TodoRemoved
|
2
|
+
include Webspicy::Specification::Postcondition
|
3
|
+
|
4
|
+
def self.match(service, descr)
|
5
|
+
return TodoRemoved.new if descr =~ /The todo has been removed/
|
6
|
+
end
|
7
|
+
|
8
|
+
def check(invocation)
|
9
|
+
client = invocation.client
|
10
|
+
id = invocation.test_case.params['id']
|
11
|
+
url = "/todo/#{id}"
|
12
|
+
response = client.api.get(url, {}, {
|
13
|
+
"Accept" => "application/json"
|
14
|
+
})
|
15
|
+
return nil if response.status == 404
|
16
|
+
"Todo `#{id}` was not deleted, it has been found"
|
17
|
+
end
|
18
|
+
end
|