webspicy 0.12.5 → 0.13.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
  SHA256:
3
- metadata.gz: c3d8a8db807de1959e59ebc27dec02a35c11749763c64932c4b38be2c763375f
4
- data.tar.gz: d8bdd2e5e1dfc7dfbf25034ccb5867f93b1dd09d63e60225c78f30b0d9577a22
3
+ metadata.gz: df662e6e4d8e94403071753f7f4e3a61919bf6fc8e5913316b847fee3b03d9d3
4
+ data.tar.gz: 4e18c04cff9b572d4173a267590f6e91cbfe1bbbf40236944c7fad50edff88dc
5
5
  SHA512:
6
- metadata.gz: 25f00703c45fdef554cb45d8699ed97b9bc61a1d395103260b2e1901960a21740eed8aa47f103c760b8d6e352aebb55d98377322b2fe0bdb033302d52694b50e
7
- data.tar.gz: 487fc0463160ff897ceab1ec3782ffb5c1cf89aa701970ddf0478dac71678ae458f95423aa7cdde3fbfa2c0a762fd61d3a9cfc14fe8e02efeacf978897ba5770
6
+ metadata.gz: 997f7223ba296843ff3ef1c4acaeed45815921c88e03ae756d7e27cf0c4ab60b3a644ddea34e0ac3df4bed41c3472a1135ac15801efc0052cca0c190ca5aceee
7
+ data.tar.gz: b1cdceb0a8a3b9bc756e2f7a763b4e529c4bb370d7db916d83c273f6e692cb08aa652f296571d846f3112c344d144f03117fecab9d21c7b622c0ed5867231af6
@@ -1,25 +1,29 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- webspicy (0.12.5)
5
- finitio (>= 0.6.1)
4
+ webspicy (0.13.0)
5
+ finitio (>= 0.8.0)
6
6
  http (~> 2)
7
+ mustermann (~> 1.0)
8
+ mustermann-contrib
7
9
  path (~> 1.3)
8
10
  rack-robustness (~> 1.1, >= 1.1.0)
9
11
  rack-test (~> 0.6.3)
10
12
  rspec (~> 3.7)
13
+ rspec_junit_formatter (~> 0.4.1)
11
14
 
12
15
  GEM
13
16
  remote: https://rubygems.org/
14
17
  specs:
15
- addressable (2.6.0)
16
- public_suffix (>= 2.0.2, < 4.0)
18
+ addressable (2.7.0)
19
+ public_suffix (>= 2.0.2, < 5.0)
17
20
  citrus (3.0.2)
18
21
  diff-lcs (1.3)
19
22
  domain_name (0.5.20190701)
20
23
  unf (>= 0.0.5, < 1.0.0)
21
- finitio (0.7.0)
24
+ finitio (0.8.0)
22
25
  citrus (>= 2.4, < 4.0)
26
+ hansi (0.2.0)
23
27
  http (2.2.2)
24
28
  addressable (~> 2.3)
25
29
  http-cookie (~> 1.0)
@@ -30,34 +34,39 @@ GEM
30
34
  http-form_data (1.0.3)
31
35
  http_parser.rb (0.6.0)
32
36
  mustermann (1.0.3)
37
+ mustermann-contrib (1.0.3)
38
+ hansi (~> 0.2.0)
39
+ mustermann (= 1.0.3)
33
40
  path (1.3.3)
34
- public_suffix (3.1.1)
41
+ public_suffix (4.0.3)
35
42
  rack (2.0.7)
36
- rack-protection (2.0.5)
43
+ rack-protection (2.0.7)
37
44
  rack
38
45
  rack-robustness (1.1.0)
39
46
  rack-test (0.6.3)
40
47
  rack (>= 1.0)
41
48
  rake (10.5.0)
42
- rspec (3.8.0)
43
- rspec-core (~> 3.8.0)
44
- rspec-expectations (~> 3.8.0)
45
- rspec-mocks (~> 3.8.0)
46
- rspec-core (3.8.2)
47
- rspec-support (~> 3.8.0)
48
- rspec-expectations (3.8.4)
49
+ rspec (3.9.0)
50
+ rspec-core (~> 3.9.0)
51
+ rspec-expectations (~> 3.9.0)
52
+ rspec-mocks (~> 3.9.0)
53
+ rspec-core (3.9.1)
54
+ rspec-support (~> 3.9.1)
55
+ rspec-expectations (3.9.0)
49
56
  diff-lcs (>= 1.2.0, < 2.0)
50
- rspec-support (~> 3.8.0)
51
- rspec-mocks (3.8.1)
57
+ rspec-support (~> 3.9.0)
58
+ rspec-mocks (3.9.1)
52
59
  diff-lcs (>= 1.2.0, < 2.0)
53
- rspec-support (~> 3.8.0)
54
- rspec-support (3.8.2)
55
- sinatra (2.0.5)
60
+ rspec-support (~> 3.9.0)
61
+ rspec-support (3.9.2)
62
+ rspec_junit_formatter (0.4.1)
63
+ rspec-core (>= 2, < 4, != 2.12.0)
64
+ sinatra (2.0.7)
56
65
  mustermann (~> 1.0)
57
66
  rack (~> 2.0)
58
- rack-protection (= 2.0.5)
67
+ rack-protection (= 2.0.7)
59
68
  tilt (~> 2.0)
60
- tilt (2.0.9)
69
+ tilt (2.0.10)
61
70
  unf (0.1.4)
62
71
  unf_ext
63
72
  unf_ext (0.0.7.6)
@@ -71,4 +80,4 @@ DEPENDENCIES
71
80
  webspicy!
72
81
 
73
82
  BUNDLED WITH
74
- 2.0.1
83
+ 2.1.0.pre.1
data/lib/webspicy.rb CHANGED
@@ -7,6 +7,7 @@ require 'ostruct'
7
7
  require 'yaml'
8
8
  require 'rspec'
9
9
  require 'rack/test'
10
+ require "mustermann"
10
11
  module Webspicy
11
12
 
12
13
  ###
@@ -49,7 +49,7 @@ module Webspicy
49
49
  @last_response = HTTP[headers || {}].options(url, params: params)
50
50
 
51
51
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
52
- Webspicy.debug("Response: #{@last_response.body}")
52
+ Webspicy.debug("Response (#{@last_response.status}): #{@last_response.body}")
53
53
 
54
54
  @last_response
55
55
  end
@@ -60,7 +60,7 @@ module Webspicy
60
60
  @last_response = HTTP[headers || {}].get(url, params: params)
61
61
 
62
62
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
63
- Webspicy.debug("Response: #{@last_response.body}")
63
+ Webspicy.debug("Response (#{@last_response.status}): #{@last_response.body}")
64
64
 
65
65
  @last_response
66
66
  end
@@ -88,7 +88,7 @@ module Webspicy
88
88
  end
89
89
 
90
90
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
91
- Webspicy.debug("Response: #{@last_response.body}")
91
+ Webspicy.debug("Response (#{@last_response.status}): #{@last_response.body}")
92
92
 
93
93
  @last_response
94
94
  end
@@ -101,7 +101,7 @@ module Webspicy
101
101
  @last_response = HTTP[headers].patch(url, body: params.to_json)
102
102
 
103
103
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
104
- Webspicy.debug("Response: #{@last_response.body}")
104
+ Webspicy.debug("Response (#{@last_response.status}): #{@last_response.body}")
105
105
 
106
106
  @last_response
107
107
  end
@@ -112,7 +112,7 @@ module Webspicy
112
112
  @last_response = HTTP[headers || {}].post(url, form: params)
113
113
 
114
114
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
115
- Webspicy.debug("Response: #{@last_response.body}")
115
+ Webspicy.debug("Response (#{@last_response.status}): #{@last_response.body}")
116
116
 
117
117
  @last_response
118
118
  end
@@ -123,7 +123,7 @@ module Webspicy
123
123
  @last_response = HTTP[headers || {}].delete(url, body: params.to_json)
124
124
 
125
125
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
126
- Webspicy.debug("Response: #{@last_response.body}")
126
+ Webspicy.debug("Response (#{@last_response.status}): #{@last_response.body}")
127
127
 
128
128
  @last_response
129
129
  end
@@ -70,7 +70,7 @@ module Webspicy
70
70
  @last_response = handler.last_response
71
71
 
72
72
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
73
- Webspicy.debug("Response: #{@last_response.body}")
73
+ Webspicy.debug("Response (#{@last_response.status}): #{@last_response.body}")
74
74
 
75
75
  @last_response
76
76
  end
@@ -85,7 +85,7 @@ module Webspicy
85
85
  @last_response = handler.last_response
86
86
 
87
87
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
88
- Webspicy.debug("Response: #{@last_response.body}")
88
+ Webspicy.debug("Response (#{@last_response.status}): #{@last_response.body}")
89
89
 
90
90
  @last_response
91
91
  end
@@ -110,7 +110,7 @@ module Webspicy
110
110
  @last_response = handler.last_response
111
111
 
112
112
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
113
- Webspicy.debug("Response: #{@last_response.body}")
113
+ Webspicy.debug("Response (#{@last_response.status}): #{@last_response.body}")
114
114
 
115
115
  @last_response
116
116
  end
@@ -124,7 +124,7 @@ module Webspicy
124
124
  @last_response = handler.last_response
125
125
 
126
126
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
127
- Webspicy.debug("Response: #{@last_response.body}")
127
+ Webspicy.debug("Response (#{@last_response.status}): #{@last_response.body}")
128
128
 
129
129
  @last_response
130
130
  end
@@ -138,7 +138,7 @@ module Webspicy
138
138
  @last_response = handler.last_response
139
139
 
140
140
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
141
- Webspicy.debug("Response: #{@last_response.body}")
141
+ Webspicy.debug("Response (#{@last_response.status}): #{@last_response.body}")
142
142
 
143
143
  @last_response
144
144
  end
@@ -152,7 +152,7 @@ module Webspicy
152
152
  @last_response = handler.last_response
153
153
 
154
154
  Webspicy.debug("Headers: #{@last_response.headers.to_hash}")
155
- Webspicy.debug("Response: #{@last_response.body}")
155
+ Webspicy.debug("Response (#{@last_response.status}): #{@last_response.body}")
156
156
 
157
157
  @last_response
158
158
  end
@@ -273,7 +273,8 @@ module Webspicy
273
273
  # - FAILFAST <-> --fail-fast
274
274
  #
275
275
  def default_rspec_options
276
- options = ["--color", "--format=documentation"]
276
+ dest_folder = (self.folder/'rspec.xml').to_s
277
+ options = %w{--color --format=documentation --format RspecJunitFormatter --out} << dest_folder
277
278
  if ENV['FAILFAST']
278
279
  options << (ENV['FAILFAST'] == 'no' ? "--no-fail-fast" : "--fail-fast=#{ENV['FAILFAST']}")
279
280
  end
@@ -299,6 +300,13 @@ module Webspicy
299
300
  end
300
301
  end
301
302
 
303
+ # Returns the data generator to use, for generating random data when
304
+ # needed.
305
+ def generator
306
+ @generator
307
+ end
308
+ attr_writer :generator
309
+
302
310
  # Duplicates this configuration and yields the block with the new one,
303
311
  # if a block is given.
304
312
  #
@@ -0,0 +1,88 @@
1
+ require "finitio/generation"
2
+ require "json"
3
+ module Webspicy
4
+ class Mocker
5
+
6
+ def initialize(config)
7
+ @config = Configuration.dress(config)
8
+ @generator = config.generator || Finitio::Generation.new
9
+ end
10
+ attr_reader :config, :generator
11
+
12
+ def call(env)
13
+ req = Rack::Request.new(env)
14
+ path = req.path
15
+ meth = req.request_method
16
+ if meth == "OPTIONS" && has_service?(path)
17
+ [204, {}, []]
18
+ elsif service = find_service(meth, path)
19
+ status = best_status_code(service)
20
+ body = status == 204 ? "" : random_body(service, req)
21
+ headers = generate_headers(service)
22
+ [ status, headers, [ body ].compact ]
23
+ else
24
+ [404, {}, []]
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def has_service?(path)
31
+ config.each_scope do |scope|
32
+ scope.each_resource do |resource|
33
+ next unless url_matches?(resource, path)
34
+ return true
35
+ end
36
+ end
37
+ return false
38
+ end
39
+
40
+ def find_service(method, path)
41
+ config.each_scope do |scope|
42
+ scope.each_resource do |resource|
43
+ next unless url_matches?(resource, path)
44
+ scope.each_service(resource) do |service|
45
+ return service if service.method == method
46
+ end
47
+ end
48
+ end
49
+ nil
50
+ end
51
+
52
+ def generate_headers(service)
53
+ {
54
+ "Content-Type" => best_content_type(service)
55
+ }.delete_if{|k,v| v.nil? }
56
+ end
57
+
58
+ def best_status_code(service)
59
+ if ex = service.examples.first
60
+ ex.expected_status || 200
61
+ else
62
+ 200
63
+ end
64
+ end
65
+
66
+ def best_content_type(service)
67
+ if ex = service.examples.first
68
+ ex.expected_content_type
69
+ else
70
+ "application/json"
71
+ end
72
+ end
73
+
74
+ def url_matches?(resource, path)
75
+ resource.url_pattern.match(path)
76
+ end
77
+
78
+ def random_body(service, request)
79
+ world = OpenStruct.new({
80
+ service: service,
81
+ request: request
82
+ })
83
+ data = generator.call(service.output_schema.main, world)
84
+ JSON.pretty_generate(data) if data
85
+ end
86
+
87
+ end # class Mocker
88
+ end # module Webspicy
@@ -26,6 +26,10 @@ module Webspicy
26
26
  @raw[:url]
27
27
  end
28
28
 
29
+ def url_pattern
30
+ @url_pattern ||= Mustermann.new(url, type: :template)
31
+ end
32
+
29
33
  def services
30
34
  @raw[:services]
31
35
  end
@@ -20,7 +20,7 @@ module Webspicy
20
20
  tester = self
21
21
  RSpec.reset
22
22
  rspec_config!
23
- RSpec.describe "Webspicy test suite" do
23
+ RSpec.describe "" do
24
24
  before(:all) do
25
25
  tester.config.listeners(:before_all).each do |l|
26
26
  l.call(tester.config)
@@ -71,15 +71,26 @@ module Webspicy
71
71
  @invocation
72
72
  end
73
73
 
74
- it 'meets its specification' do
75
- expect(invocation.done?).to eq(true)
76
- expect(invocation.expected_status_unmet).to(be_nil)
77
- expect(invocation.expected_content_type_unmet).to(be_nil)
78
- expect(invocation.expected_headers_unmet).to(be_nil) if test_case.has_expected_headers?
79
- expect(invocation.expected_schema_unmet).to(be_nil)
80
- expect(invocation.assertions_unmet).to(be_nil) if test_case.has_assertions?
81
- expect(invocation.postconditions_unmet).to(be_nil) if test_case.service.has_postconditions? and not(counterexample)
82
- expect(invocation.expected_error_unmet).to(be_nil) if test_case.has_expected_error?
74
+ it 'works' do
75
+ raise "Test not ran" unless invocation.done?
76
+ fails = [
77
+ [:expected_status_unmet, true],
78
+ [:expected_content_type_unmet, true],
79
+ [:expected_headers_unmet, test_case.has_expected_headers?],
80
+ [:expected_schema_unmet, true],
81
+ [:assertions_unmet, test_case.has_assertions?],
82
+ [:postconditions_unmet, test_case.service.has_postconditions? && !counterexample],
83
+ [:expected_error_unmet, test_case.has_expected_error?]
84
+ ].map do |(expectation,only_if)|
85
+ next unless only_if
86
+ begin
87
+ invocation.send(expectation)
88
+ rescue => ex
89
+ ex.message
90
+ end
91
+ end
92
+ fails = fails.compact
93
+ raise "\n* " + fails.join("\n* ") + "\n" unless fails.empty?
83
94
  end
84
95
  end
85
96
  end
@@ -1,8 +1,8 @@
1
1
  module Webspicy
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 12
5
- TINY = 5
4
+ MINOR = 13
5
+ TINY = 0
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ require 'rack/test'
3
+ require 'webspicy/mocker'
4
+ module Webspicy
5
+ describe Mocker do
6
+ include Rack::Test::Methods
7
+
8
+ let(:app) {
9
+ Mocker.new(Configuration.dress(restful_folder))
10
+ }
11
+
12
+ it 'works as expected' do
13
+ get '/todo/'
14
+ expect(last_response.status).to eql(200)
15
+ expect(last_response.body).not_to be_empty
16
+ end
17
+
18
+ it 'supports CORS on OPTIONS' do
19
+ options '/todo/'
20
+ expect(last_response.status).to eql(204)
21
+ expect(last_response.body).to be_empty
22
+ end
23
+
24
+ it 'returns the correct status code, taken from first example' do
25
+ delete '/todo/1'
26
+ expect(last_response.status).to eql(204)
27
+ expect(last_response.body).to be_empty
28
+ expect(last_response["Content-Type"]).to be_nil
29
+ end
30
+
31
+ end
32
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webspicy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.5
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-17 00:00:00.000000000 Z
11
+ date: 2020-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -58,6 +58,20 @@ dependencies:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '3.7'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec_junit_formatter
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 0.4.1
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 0.4.1
61
75
  - !ruby/object:Gem::Dependency
62
76
  name: rack-test
63
77
  requirement: !ruby/object:Gem::Requirement
@@ -78,14 +92,14 @@ dependencies:
78
92
  requirements:
79
93
  - - ">="
80
94
  - !ruby/object:Gem::Version
81
- version: 0.6.1
95
+ version: 0.8.0
82
96
  type: :runtime
83
97
  prerelease: false
84
98
  version_requirements: !ruby/object:Gem::Requirement
85
99
  requirements:
86
100
  - - ">="
87
101
  - !ruby/object:Gem::Version
88
- version: 0.6.1
102
+ version: 0.8.0
89
103
  - !ruby/object:Gem::Dependency
90
104
  name: http
91
105
  requirement: !ruby/object:Gem::Requirement
@@ -134,6 +148,34 @@ dependencies:
134
148
  - - ">="
135
149
  - !ruby/object:Gem::Version
136
150
  version: 1.1.0
151
+ - !ruby/object:Gem::Dependency
152
+ name: mustermann
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: '1.0'
158
+ type: :runtime
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: '1.0'
165
+ - !ruby/object:Gem::Dependency
166
+ name: mustermann-contrib
167
+ requirement: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ type: :runtime
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
137
179
  description: Webspicy helps testing web services as software operation black boxes
138
180
  email: blambeau@gmail.com
139
181
  executables: []
@@ -171,6 +213,7 @@ files:
171
213
  - lib/webspicy/configuration.rb
172
214
  - lib/webspicy/file_upload.rb
173
215
  - lib/webspicy/formaldoc.fio
216
+ - lib/webspicy/mocker.rb
174
217
  - lib/webspicy/postcondition.rb
175
218
  - lib/webspicy/precondition.rb
176
219
  - lib/webspicy/resource.rb
@@ -184,6 +227,7 @@ files:
184
227
  - lib/webspicy/version.rb
185
228
  - spec/unit/client/test_around.rb
186
229
  - spec/unit/configuration/config.rb
230
+ - spec/unit/mocker/test_mocker.rb
187
231
  - spec/unit/resource/service/test_dress_params.rb
188
232
  - spec/unit/resource/test_instantiate_url.rb
189
233
  - spec/unit/resource/test_url_placeholders.rb
@@ -215,8 +259,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
215
259
  - !ruby/object:Gem::Version
216
260
  version: '0'
217
261
  requirements: []
218
- rubyforge_project:
219
- rubygems_version: 2.7.6
262
+ rubygems_version: 3.1.0.pre1
220
263
  signing_key:
221
264
  specification_version: 4
222
265
  summary: Webspicy helps testing web services as software operation black boxes!