webspicy 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41838b2f4db0842af70e1449780812ed8e211551
4
- data.tar.gz: 51d875cc4515fa99e8c5f643f8086ee6b8cbe989
3
+ metadata.gz: 2f7e458fbf3c7ac65bd95574e127f16791f56391
4
+ data.tar.gz: e2cdfa60d3e9ba3831bd49cb4a6931e675752eea
5
5
  SHA512:
6
- metadata.gz: 1f2d125ccb018ab4e4b524cf5798024474084ea7ff8b46f036b2418a300072bf21814cae586cbf65d7de3ce4fef3f8b7712d67783a8ab9260edec20fa74b7b99
7
- data.tar.gz: 1d2bfa5d4009220a4b4cb1aabbdc1a17017c02281cd1c497c1b1a909867aca21ae29566ce3f8dc03d1a3d7d264497c37e2b03fc2071b6db9b9703d25f5be157f
6
+ metadata.gz: 94edf71925034c01b1297c58e049f2f4729330c80e4db0e601e24f9409b6d609f88b24b8b8f8c707d3d6e52c7cf18dc137d948d4728e222e2305bf097ca1dfd8
7
+ data.tar.gz: a88aecd9681674821f4953e96519635f1a2a5d452abf100de57de0fd8d01b7121f54a72f97252384be4d23e2c93dcee5d6518f1b2ff1f1ef317d8e8de07c99b0
@@ -5,3 +5,4 @@ gem 'sinatra', "~> 2.0"
5
5
  gem "path", "~> 1.3"
6
6
  gem "finitio", "~> 0.5.2"
7
7
  gem "webspicy", path: "../.."
8
+ gem "rack-robustness", "~> 1.1.0"
@@ -1,25 +1,26 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- webspicy (0.3.0.pre.rc2)
4
+ webspicy (0.5.0.pre.rc0)
5
5
  finitio (~> 0.5.2)
6
6
  http (~> 2)
7
7
  path (~> 1.3)
8
+ rack-robustness (~> 1.1.0)
8
9
  rack-test (~> 0.6.3)
9
10
  rspec (~> 3.6)
10
11
 
11
12
  GEM
12
13
  remote: https://rubygems.org/
13
14
  specs:
14
- addressable (2.5.1)
15
- public_suffix (~> 2.0, >= 2.0.2)
15
+ addressable (2.5.2)
16
+ public_suffix (>= 2.0.2, < 4.0)
16
17
  citrus (3.0.2)
17
18
  diff-lcs (1.3)
18
19
  domain_name (0.5.20170404)
19
20
  unf (>= 0.0.5, < 1.0.0)
20
21
  finitio (0.5.2)
21
22
  citrus (>= 2.4, < 4.0)
22
- http (2.2.1)
23
+ http (2.2.2)
23
24
  addressable (~> 2.3)
24
25
  http-cookie (~> 1.0)
25
26
  http-form_data (~> 1.0.1)
@@ -30,10 +31,11 @@ GEM
30
31
  http_parser.rb (0.6.0)
31
32
  mustermann (1.0.0)
32
33
  path (1.3.3)
33
- public_suffix (2.0.5)
34
+ public_suffix (3.0.0)
34
35
  rack (2.0.3)
35
36
  rack-protection (2.0.0)
36
37
  rack
38
+ rack-robustness (1.1.0)
37
39
  rack-test (0.6.3)
38
40
  rack (>= 1.0)
39
41
  rake (10.5.0)
@@ -66,6 +68,7 @@ PLATFORMS
66
68
  DEPENDENCIES
67
69
  finitio (~> 0.5.2)
68
70
  path (~> 1.3)
71
+ rack-robustness (~> 1.1.0)
69
72
  rake (~> 10)
70
73
  sinatra (~> 2.0)
71
74
  webspicy!
@@ -2,6 +2,7 @@ require 'sinatra'
2
2
  require 'json'
3
3
  require 'path'
4
4
  require 'finitio'
5
+ require 'rack/robustness'
5
6
 
6
7
  SCHEMA = Finitio::DEFAULT_SYSTEM.parse (Path.dir/'webspicy/schema.fio').read
7
8
 
@@ -21,6 +22,15 @@ enable :raise_errors
21
22
 
22
23
  set :todolist, TODOLIST.dup
23
24
 
25
+ use Rack::Robustness do |g|
26
+ g.no_catch_all
27
+ g.status 400
28
+ g.content_type 'application/json'
29
+ g.body{|ex| { error: ex.message }.to_json }
30
+ g.on(Finitio::TypeError)
31
+ end
32
+
33
+
24
34
  post '/reset' do
25
35
  settings.todolist = TODOLIST.dup
26
36
  status 200
@@ -56,6 +66,21 @@ get '/todo/:id' do |id|
56
66
  end
57
67
  end
58
68
 
69
+ patch '/todo/:id' do |id|
70
+ content_type :json
71
+ todo = settings.todolist.find{|todo| todo[:id] == Integer(id) }
72
+ if todo.nil?
73
+ status 404
74
+ {error: "No such todo"}.to_json
75
+ else
76
+ patch = SCHEMA["TodoPatch"].dress(JSON.load(request.body.read))
77
+ patched = todo.merge(patch)
78
+ settings.todolist = settings.todolist.reject{|todo| todo[:id] == Integer(id) }
79
+ settings.todolist << patched
80
+ patched.to_json
81
+ end
82
+ end
83
+
59
84
  delete '/todo/:id' do |id|
60
85
  content_type :json
61
86
  todo = settings.todolist.find{|todo| todo[:id] == Integer(id) }
@@ -2,3 +2,12 @@ Todo = {
2
2
  id : Integer
3
3
  description : String
4
4
  }
5
+
6
+ TodoPatch = {
7
+ id :? Integer
8
+ description :? String
9
+ }
10
+
11
+ ErrorSchema = {
12
+ error: String
13
+ }
@@ -23,9 +23,7 @@ services:
23
23
  .
24
24
 
25
25
  error_schema: |-
26
- {
27
- error: String
28
- }
26
+ ErrorSchema
29
27
 
30
28
  examples:
31
29
 
@@ -23,9 +23,7 @@ services:
23
23
  Todo
24
24
 
25
25
  error_schema: |-
26
- {
27
- error: String
28
- }
26
+ ErrorSchema
29
27
 
30
28
  examples:
31
29
 
@@ -22,8 +22,7 @@ services:
22
22
  [Todo]
23
23
 
24
24
  error_schema: |-
25
- {
26
- }
25
+ ErrorSchema
27
26
 
28
27
  examples:
29
28
 
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: |-
3
+ Todo
4
+
5
+ url: |-
6
+ /todo/{id}
7
+
8
+ services:
9
+ - method: |-
10
+ PATCH
11
+
12
+ description: |-
13
+ Patches a single Todo item
14
+
15
+ preconditions: |-
16
+
17
+ input_schema: |-
18
+ TodoPatch
19
+
20
+ output_schema: |-
21
+ Todo
22
+
23
+ error_schema: |-
24
+ ErrorSchema
25
+
26
+ examples:
27
+
28
+ - description: |-
29
+ when requested on an existing TODO
30
+ params:
31
+ id: 1
32
+ description: 'hello world'
33
+ expected:
34
+ content_type: application/json
35
+ status: 200
36
+ assert:
37
+ - "pathFD('', description: 'hello world')"
38
+
39
+ counterexamples:
40
+
41
+ - description: |-
42
+ when requested on an unexisting TODO
43
+ params:
44
+ id: 999254654
45
+ expected:
46
+ content_type: application/json
47
+ status: 404
48
+ assert:
49
+ - "pathFD('', error: 'No such todo')"
50
+
51
+ - description: |-
52
+ when violating the Patch data type
53
+ params:
54
+ id: 1
55
+ nosuchone: 'foobar'
56
+ dress_params:
57
+ false
58
+ expected:
59
+ content_type: application/json
60
+ status: 400
@@ -21,9 +21,7 @@ services:
21
21
  Todo
22
22
 
23
23
  error_schema: |-
24
- {
25
- error: String
26
- }
24
+ ErrorSchema
27
25
 
28
26
  examples:
29
27
 
@@ -24,7 +24,7 @@ module Webspicy
24
24
  api.public_send(service.method.to_s.downcase.to_sym, url, params, headers)
25
25
 
26
26
  # Return the result
27
- Resource::Service::Invocation.new(service, test_case, api.last_response)
27
+ Resource::Service::Invocation.new(service, test_case, api.last_response, self)
28
28
  end
29
29
 
30
30
  class Api
@@ -38,6 +38,8 @@ module Webspicy
38
38
 
39
39
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
40
40
  Webspicy.debug("Response: #{@last_response.body}")
41
+
42
+ @last_response
41
43
  end
42
44
 
43
45
  def post(url, params = {}, headers = nil)
@@ -47,6 +49,19 @@ module Webspicy
47
49
 
48
50
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
49
51
  Webspicy.debug("Response: #{@last_response.body}")
52
+
53
+ @last_response
54
+ end
55
+
56
+ def patch(url, params = {}, headers = nil)
57
+ Webspicy.info("PATCH #{url} -- #{params.inspect}")
58
+
59
+ @last_response = HTTP[headers || {}].patch(url, body: params.to_json)
60
+
61
+ Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
62
+ Webspicy.debug("Response: #{@last_response.body}")
63
+
64
+ @last_response
50
65
  end
51
66
 
52
67
  def post_form(url, params = {}, headers = nil)
@@ -56,6 +71,8 @@ module Webspicy
56
71
 
57
72
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
58
73
  Webspicy.debug("Response: #{@last_response.body}")
74
+
75
+ @last_response
59
76
  end
60
77
 
61
78
  def delete(url, params = {}, headers = nil)
@@ -65,6 +82,8 @@ module Webspicy
65
82
 
66
83
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
67
84
  Webspicy.debug("Response: #{@last_response.body}")
85
+
86
+ @last_response
68
87
  end
69
88
 
70
89
  end
@@ -5,13 +5,11 @@ module Webspicy
5
5
  Factory.new(app)
6
6
  end
7
7
 
8
- def initialize(scope, app, domain)
8
+ def initialize(scope, app)
9
9
  super(scope)
10
10
  @api = Api.new(app)
11
- @domain = domain
12
11
  end
13
12
  attr_reader :api
14
- attr_reader :domain
15
13
 
16
14
  def call(test_case)
17
15
  service, resource = test_case.service, test_case.resource
@@ -22,13 +20,13 @@ module Webspicy
22
20
 
23
21
  # Instantiate the url and strip parameters
24
22
  url, params = resource.instantiate_url(params)
25
- url = "http://#{domain}#{url}" if domain
23
+ url = scope.to_real_url(url){ url }
26
24
 
27
25
  # Invoke the service now
28
26
  api.public_send(service.method.to_s.downcase.to_sym, url, params, headers)
29
27
 
30
28
  # Return the result
31
- Resource::Service::Invocation.new(service, test_case, api.last_response)
29
+ Resource::Service::Invocation.new(service, test_case, api.last_response, self)
32
30
  end
33
31
 
34
32
  class Factory
@@ -37,15 +35,9 @@ module Webspicy
37
35
  @app = app
38
36
  end
39
37
  attr_reader :app
40
- attr_reader :domain
41
-
42
- def on(domain)
43
- @domain = domain
44
- self
45
- end
46
38
 
47
39
  def new(scope)
48
- RackTestClient.new(scope, app, domain)
40
+ RackTestClient.new(scope, app)
49
41
  end
50
42
 
51
43
  end # class Factory
@@ -78,6 +70,8 @@ module Webspicy
78
70
 
79
71
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
80
72
  Webspicy.debug("Response: #{@last_response.body}")
73
+
74
+ @last_response
81
75
  end
82
76
 
83
77
  def post(url, params = {}, headers = nil)
@@ -90,6 +84,22 @@ module Webspicy
90
84
 
91
85
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
92
86
  Webspicy.debug("Response: #{@last_response.body}")
87
+
88
+ @last_response
89
+ end
90
+
91
+ def patch(url, params = {}, headers = nil)
92
+ handler = get_handler(headers)
93
+
94
+ Webspicy.info("PATCH #{url} -- #{params.inspect} -- #{headers.inspect}")
95
+
96
+ handler.patch(url, params.to_json, {"CONTENT_TYPE" => "application/json"})
97
+ @last_response = handler.last_response
98
+
99
+ Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
100
+ Webspicy.debug("Response: #{@last_response.body}")
101
+
102
+ @last_response
93
103
  end
94
104
 
95
105
  def post_form(url, params = {}, headers = nil)
@@ -102,6 +112,8 @@ module Webspicy
102
112
 
103
113
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
104
114
  Webspicy.debug("Response: #{@last_response.body}")
115
+
116
+ @last_response
105
117
  end
106
118
 
107
119
  def delete(url, params = {}, headers = nil)
@@ -114,6 +126,8 @@ module Webspicy
114
126
 
115
127
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
116
128
  Webspicy.debug("Response: #{@last_response.body}")
129
+
130
+ @last_response
117
131
  end
118
132
 
119
133
  private
@@ -3,13 +3,14 @@ module Webspicy
3
3
  class Service
4
4
  class Invocation
5
5
 
6
- def initialize(service, test_case, response)
6
+ def initialize(service, test_case, response, client)
7
7
  @service = service
8
8
  @test_case = test_case
9
9
  @response = response
10
+ @client = client
10
11
  end
11
12
 
12
- attr_reader :service, :test_case, :response
13
+ attr_reader :service, :test_case, :response, :client
13
14
 
14
15
  ### Getters on response
15
16
 
@@ -75,7 +75,7 @@ module Webspicy
75
75
 
76
76
  def instrument
77
77
  service.preconditions.each do |pre|
78
- pre.ensure(self)
78
+ pre.instrument(self)
79
79
  end
80
80
  end
81
81
 
@@ -93,8 +93,12 @@ module Webspicy
93
93
  end
94
94
 
95
95
  # Convert an instantiated URL found in a webservice definition
96
- # to a real URL, using the configuration host
97
- def to_real_url(url)
96
+ # to a real URL, using the configuration host.
97
+ #
98
+ # When no host resolved on the configuration and the url is not
99
+ # already an absolute URL, yields the block if given, or raise
100
+ # an exception.
101
+ def to_real_url(url, &bl)
98
102
  case config.host
99
103
  when Proc
100
104
  config.host.call(url)
@@ -102,6 +106,7 @@ module Webspicy
102
106
  url =~ /^http/ ? url : "#{config.host}#{url}"
103
107
  else
104
108
  return url if url =~ /^http/
109
+ return yield(url) if block_given?
105
110
  raise "Unable to resolve `#{url}` : no host resolver provided\nSee `Configuration#host="
106
111
  end
107
112
  end
@@ -1,8 +1,8 @@
1
1
  module Webspicy
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 4
5
- TINY = 2
4
+ MINOR = 5
5
+ TINY = 0
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
@@ -18,7 +18,12 @@ module Webspicy
18
18
  expect(got).to eql(url)
19
19
  end
20
20
 
21
- it 'fails on relative URLs' do
21
+ it 'yields the block relative URLs' do
22
+ got = scope.to_real_url("/todo"){ "hello" }
23
+ expect(got).to eql("hello")
24
+ end
25
+
26
+ it 'fails on relative URLs and no block is given' do
22
27
  expect(->(){
23
28
  scope.to_real_url("/todo")
24
29
  }).to raise_error(/Unable to resolve `\/todo`/)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webspicy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '1.3'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rack-robustness
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 1.1.0
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 1.1.0
111
125
  description: Webspicy helps testing web services as software operation black boxes
112
126
  email: blambeau@gmail.com
113
127
  executables: []
@@ -129,6 +143,7 @@ files:
129
143
  - examples/restful/webspicy/todo/deleteTodo.yml
130
144
  - examples/restful/webspicy/todo/getTodo.yml
131
145
  - examples/restful/webspicy/todo/getTodos.yml
146
+ - examples/restful/webspicy/todo/patchTodo.yml
132
147
  - examples/restful/webspicy/todo/postTodos.yml
133
148
  - lib/webspicy.rb
134
149
  - lib/webspicy/checker.rb