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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +71 -24
  3. data/bin/webspicy +30 -14
  4. data/examples/restful/Gemfile +2 -2
  5. data/examples/restful/Gemfile.lock +53 -33
  6. data/examples/restful/Rakefile +0 -1
  7. data/examples/restful/app.rb +4 -1
  8. data/examples/restful/webspicy/config.rb +8 -0
  9. data/examples/restful/webspicy/rack.rb +1 -1
  10. data/examples/restful/webspicy/real.rb +1 -1
  11. data/examples/restful/webspicy/schema.fio +2 -2
  12. data/examples/restful/webspicy/support/must_be_authenticated.rb +2 -2
  13. data/examples/restful/webspicy/support/todo_removed.rb +18 -0
  14. data/examples/restful/webspicy/todo/deleteTodo.yml +4 -1
  15. data/examples/restful/webspicy/todo/getTodoSingleServiceFormat.yml +46 -0
  16. data/examples/restful/webspicy/todo/options.yml +1 -1
  17. data/examples/restful/webspicy/todo/patchTodo.yml +3 -0
  18. data/examples/restful/webspicy/todo/postFile.yml +1 -1
  19. data/examples/single_spec/spec.yml +59 -0
  20. data/examples/website/config.rb +2 -0
  21. data/examples/website/schema.fio +1 -0
  22. data/examples/website/specification/get-http.yml +30 -0
  23. data/examples/website/specification/get-https.yml +30 -0
  24. data/lib/finitio/webspicy/scalars.fio +25 -0
  25. data/lib/webspicy.rb +48 -17
  26. data/lib/webspicy/checker.rb +2 -2
  27. data/lib/webspicy/configuration.rb +70 -14
  28. data/lib/webspicy/configuration/scope.rb +162 -0
  29. data/lib/webspicy/configuration/single_url.rb +58 -0
  30. data/lib/webspicy/configuration/single_yml_file.rb +30 -0
  31. data/lib/webspicy/formaldoc.fio +23 -8
  32. data/lib/webspicy/mocker.rb +8 -8
  33. data/lib/webspicy/mocker/config.ru +5 -0
  34. data/lib/webspicy/openapi.rb +1 -0
  35. data/lib/webspicy/openapi/generator.rb +127 -0
  36. data/lib/webspicy/{resource.rb → specification.rb} +28 -5
  37. data/lib/webspicy/specification/file_upload.rb +37 -0
  38. data/lib/webspicy/specification/postcondition.rb +16 -0
  39. data/lib/webspicy/specification/precondition.rb +19 -0
  40. data/lib/webspicy/specification/precondition/global_request_headers.rb +35 -0
  41. data/lib/webspicy/specification/precondition/robust_to_invalid_input.rb +68 -0
  42. data/lib/webspicy/{resource → specification}/service.rb +11 -6
  43. data/lib/webspicy/specification/test_case.rb +139 -0
  44. data/lib/webspicy/support.rb +1 -0
  45. data/lib/webspicy/support/colorize.rb +28 -0
  46. data/lib/webspicy/support/status_range.rb +6 -1
  47. data/lib/webspicy/tester.rb +16 -11
  48. data/lib/webspicy/tester/asserter.rb +3 -2
  49. data/lib/webspicy/tester/assertions.rb +5 -1
  50. data/lib/webspicy/tester/client.rb +63 -0
  51. data/lib/webspicy/tester/client/http_client.rb +154 -0
  52. data/lib/webspicy/tester/client/rack_test_client.rb +188 -0
  53. data/lib/webspicy/tester/client/support.rb +65 -0
  54. data/lib/webspicy/tester/invocation.rb +218 -0
  55. data/lib/webspicy/tester/rspec_asserter.rb +108 -0
  56. data/lib/webspicy/tester/rspec_matchers.rb +104 -0
  57. data/lib/webspicy/version.rb +2 -2
  58. data/spec/{unit/spec_helper.rb → spec_helper.rb} +0 -0
  59. data/spec/unit/configuration/scope/test_each_service.rb +49 -0
  60. data/spec/unit/configuration/scope/test_each_specification.rb +68 -0
  61. data/spec/unit/configuration/scope/test_expand_example.rb +65 -0
  62. data/spec/unit/configuration/scope/test_to_real_url.rb +82 -0
  63. data/spec/unit/openapi/test_generator.rb +28 -0
  64. data/spec/unit/specification/precondition/test_global_request_headers.rb +42 -0
  65. data/spec/unit/{resource → specification}/service/test_dress_params.rb +2 -2
  66. data/spec/unit/specification/test_case/test_mutate.rb +24 -0
  67. data/spec/unit/{resource → specification}/test_instantiate_url.rb +5 -5
  68. data/spec/unit/{resource → specification}/test_url_placeholders.rb +4 -4
  69. data/spec/unit/test_configuration.rb +24 -7
  70. data/spec/unit/tester/client/test_around.rb +61 -0
  71. data/spec/unit/tester/test_asserter.rb +51 -0
  72. data/spec/unit/tester/test_assertions.rb +4 -4
  73. data/tasks/test.rake +3 -1
  74. metadata +88 -45
  75. data/LICENSE.md +0 -22
  76. data/lib/webspicy/client.rb +0 -61
  77. data/lib/webspicy/client/http_client.rb +0 -145
  78. data/lib/webspicy/client/rack_test_client.rb +0 -181
  79. data/lib/webspicy/client/support.rb +0 -48
  80. data/lib/webspicy/file_upload.rb +0 -35
  81. data/lib/webspicy/postcondition.rb +0 -14
  82. data/lib/webspicy/precondition.rb +0 -15
  83. data/lib/webspicy/resource/service/invocation.rb +0 -212
  84. data/lib/webspicy/resource/service/test_case.rb +0 -132
  85. data/lib/webspicy/scope.rb +0 -160
  86. data/spec/unit/client/test_around.rb +0 -59
  87. data/spec/unit/scope/test_each_resource.rb +0 -66
  88. data/spec/unit/scope/test_each_service.rb +0 -47
  89. data/spec/unit/scope/test_expand_example.rb +0 -63
  90. 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: f4a2e0e1d1ccfacade6173f0ebe8119a71438aeb5403af05bdf08373f98630d7
4
- data.tar.gz: 063a4f40b5e8244adc654bb0e60b2dccb67b930b0ec4fa18045e3b005392004d
3
+ metadata.gz: 7cbfb644d2ae34f2e2e87aa2d69b50b762299770b9c0109fbc5281fdd3b80d22
4
+ data.tar.gz: 6bf17b7423bb6ff33b53d8f12dc761094e613961487c146c66a87ce84b792bc7
5
5
  SHA512:
6
- metadata.gz: bdaaf1d7e90215b5f2f4d30ab0efd42ddf08f490dcaa77cba84a822b333020d63c34980420d9b9872c2db423635cf0d0fd0193a578826a31ad950795fa8a806e
7
- data.tar.gz: 21a7cf4e9b0bbb8835284132edd029fd7221933d2cc0d044c8ca6f5fb81bfc406621cbefdd33422da1a3ce68a703a030965fd15b7da8e678693e25a78c1526e7
6
+ metadata.gz: 403ddeb22ffccd059d8450a6290f7f190d97bc45ef12a04a43a97059d733085ce4fe2865f31a5452d43c18e4244a53129ac280cd37db09b8a6ce50e76506f8f6
7
+ data.tar.gz: '095210fda4e1b4e903c1803a2cd75420a905894b06d4403e8f1019df0c43eeec10eb3952b8d06397bdb0d8a753361c01f1577f85f09ca34258386020276dcdaa'
data/README.md CHANGED
@@ -1,46 +1,93 @@
1
1
  # Webspicy
2
2
 
3
- A description, specification and test framework for web services seen as black
4
- box software operations.
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 description of RESTful web-services + their tests
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
- * Framework/language agnostic: Webspicy is written in Ruby, but can be used to
11
- test web services in any language / framework.
21
+ * Formal and human-friendly data schema with strong data matching semantics,
22
+ thanks to finitio.io
12
23
 
13
- * Black box testing: Webspicy focuses on web services seen as blackboxes. It has
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
- * Test instrumentation and generation, based on declarative PRE & POST
19
- conditions.
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 goodness for Rubyists: being written in ruby, Webspicy also supports
22
- testing Rack applications directly (through rack/test)
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
- Please have a look at the example first. It contains a simple Sinatra application
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
- ## Executing the tests using the command line
37
+ ```
38
+ gem install webspicy
39
+ ```
31
40
 
32
- Please have a look at the examples first. Then:
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
- A docker image running your tests is provided. It expects a volume with the
42
- tests to run put in `/home/app`.
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 enspirit/webspicy -v path/to/tests:/home/app
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.
@@ -1,15 +1,25 @@
1
1
  #!/usr/bin/env ruby
2
- #/ Document and test RESTful webservices
3
- #/ (c) Enspirit SPRL. Distributed under MIT licence.
4
- #/ Usage: webspicy [options] path/to/config.rb
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 do not execute counterexamples
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"){ showhelp }
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
@@ -1,5 +1,5 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem "rake", "~> 10"
4
- gem 'sinatra', "~> 2.0", ">= 2.0.2"
3
+ gem "rake", "~> 12"
4
+ gem 'sinatra', "~> 2"
5
5
  gem "webspicy", path: "../.."
@@ -1,12 +1,14 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- webspicy (0.15.7)
5
- finitio (>= 0.8.0)
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
- path (>= 1.3)
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
- diff-lcs (1.3)
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
- finitio (0.8.0)
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 (2.2.2)
37
+ http (4.4.1)
28
38
  addressable (~> 2.3)
29
39
  http-cookie (~> 1.0)
30
- http-form_data (~> 1.0.1)
31
- http_parser.rb (~> 0.6.0)
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 (1.0.3)
35
- http_parser.rb (0.6.0)
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
- path (1.3.3)
42
- public_suffix (4.0.3)
43
- rack (2.2.2)
44
- rack-protection (2.0.8.1)
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 (10.5.0)
50
- rspec (3.9.0)
51
- rspec-core (~> 3.9.0)
52
- rspec-expectations (~> 3.9.0)
53
- rspec-mocks (~> 3.9.0)
54
- rspec-core (3.9.1)
55
- rspec-support (~> 3.9.1)
56
- rspec-expectations (3.9.1)
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.9.0)
59
- rspec-mocks (3.9.1)
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.9.0)
62
- rspec-support (3.9.2)
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.8.1)
85
+ sinatra (2.1.0)
67
86
  mustermann (~> 1.0)
68
- rack (~> 2.0)
69
- rack-protection (= 2.0.8.1)
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.6)
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 (~> 10)
81
- sinatra (~> 2.0, >= 2.0.2)
100
+ rake (~> 12)
101
+ sinatra (~> 2)
82
102
  webspicy!
83
103
 
84
104
  BUNDLED WITH
85
- 2.0.2
105
+ 2.2.1
@@ -1,6 +1,5 @@
1
1
  $LOAD_PATH.unshift File.expand_path("..", __FILE__)
2
2
  require 'app'
3
- require 'webspicy'
4
3
 
5
4
  desc "Checks all .yml definition files"
6
5
  task :check do
@@ -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
@@ -1,6 +1,6 @@
1
1
  require_relative 'config'
2
2
  webspicy_config do |c|
3
- c.client = Webspicy::RackTestClient.for(::Sinatra::Application)
3
+ c.client = Webspicy::Tester::RackTestClient.for(::Sinatra::Application)
4
4
  c.before_each do |_,client|
5
5
  client.api.post "/reset"
6
6
  end
@@ -1,7 +1,7 @@
1
1
  require_relative 'config'
2
2
  webspicy_config do |c|
3
3
  c.host = "http://127.0.0.1:4567"
4
- c.client = Webspicy::HttpClient
4
+ c.client = Webspicy::Tester::HttpClient
5
5
  c.before_each do |_,client|
6
6
  client.api.post "http://127.0.0.1:4567/reset"
7
7
  end
@@ -1,4 +1,4 @@
1
- @import finitio/data
1
+ @import webspicy/scalars
2
2
 
3
3
  Todo = {
4
4
  id : Integer
@@ -6,7 +6,7 @@ Todo = {
6
6
  }
7
7
 
8
8
  TodoPatch = {
9
- id :? Integer
9
+ id : Integer
10
10
  description :? String
11
11
  }
12
12
 
@@ -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}) #{description}
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