webspicy 0.20.14 → 0.20.18

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: 2a89789c42cdaf51eb907eaf6053eef356acff66102ccb1f579bbb2a85168e56
4
- data.tar.gz: 8afcba7ec470f2689300f2f9fe4122b7e0e11981617812fc5ce031df213adeb3
3
+ metadata.gz: 91e515bc7abf0feb3e3aa3eba50edba87a50e4242240aaffb67aee547038d537
4
+ data.tar.gz: 2535c3943955ee893484c49bad9cad525c7a90f29f27fb7f891ca7c0e8cd4d33
5
5
  SHA512:
6
- metadata.gz: fe767864fe5185515cfc9e20a7e5941ba1907979f86904920811c0c44821b8dcf7901f847b310db703497c83a18278b340b6ba30a018c44233660c82657625ec
7
- data.tar.gz: 749a0253312d49f05f46e5bd3022c2b657ddccfa0046fc0bdc70a68028161fc68c6f53d0c8e1b3e1cae00e333eb8b8c6429a3034090f5a1e54ea9b8958e81f2f
6
+ metadata.gz: 992437acb1f193a70e47132cdb00951d0e8dcf40d761cd93194924a2849e8c92391591995ea1d07935c1f0bebb952e5bec177e6782c2b66898c5f16d7e4e843a
7
+ data.tar.gz: be6fadddc53304cf9ee2111a064f81b126f9fe1560d4a89b5bb6d60623aed88770c4fa13505d9403e811ee5e784c752ad771e401988bc85fecb411be96a2e92a
@@ -42,6 +42,13 @@ module Webspicy
42
42
  @subject ||= data["subject"]
43
43
  end
44
44
 
45
+ def headers
46
+ @headers ||= data["headers"].reduce(OpenStruct.new){|acc, (key, value)|
47
+ acc[key.downcase] = value
48
+ acc
49
+ }
50
+ end
51
+
45
52
  end # class Email
46
53
  end # class Fakesendgrid
47
54
  end # class Tester
@@ -11,7 +11,7 @@ module Webspicy
11
11
  attr_reader :data
12
12
 
13
13
  def from
14
- email.from
14
+ email.from[0]
15
15
  end
16
16
 
17
17
  def recipients
@@ -24,7 +24,7 @@ module Webspicy
24
24
  end
25
25
 
26
26
  def to
27
- email.to
27
+ email.to || []
28
28
  end
29
29
 
30
30
  def subject
@@ -32,13 +32,20 @@ module Webspicy
32
32
  end
33
33
 
34
34
  def cc
35
- email.cc
35
+ email.cc || []
36
36
  end
37
37
 
38
38
  def bcc
39
39
  recipients - cc - to
40
40
  end
41
41
 
42
+ def headers
43
+ @headers ||= email.header.reduce(OpenStruct.new){|acc, h|
44
+ acc[h.name.downcase] = h.unparsed_value
45
+ acc
46
+ }
47
+ end
48
+
42
49
  def email
43
50
  @email ||= Mail.read_from_string(raw_data)
44
51
  end
@@ -38,6 +38,14 @@ module Webspicy
38
38
  .first
39
39
  end
40
40
 
41
+ def headers
42
+ @headers ||= data["headerLines"]
43
+ .reduce(OpenStruct.new){|acc, h|
44
+ acc[h["key"].downcase] = h["line"].split(': ')[1..].join(': ')
45
+ acc
46
+ }
47
+ end
48
+
41
49
  end # class Email
42
50
  end # class Fakesmtp
43
51
  end # class Tester
@@ -118,13 +118,12 @@ module Webspicy
118
118
  def run_service
119
119
  scope.each_testcase(service) do |test_case|
120
120
  @test_case = test_case
121
- reporter.before_test_case
122
121
  run_test_case
123
- reporter.test_case_done
124
122
  end
125
123
  end
126
124
 
127
125
  def run_test_case
126
+ reporter.before_test_case
128
127
  hooks.fire_around(self) do
129
128
  reporter.before_each
130
129
  hooks.fire_before_each(self)
@@ -143,9 +142,9 @@ module Webspicy
143
142
  reporter.after_each
144
143
  hooks.fire_after_each(self)
145
144
  reporter.after_each_done
146
-
147
- raise FailFast if !result.success? and failfast?
148
145
  end
146
+ reporter.test_case_done
147
+ raise FailFast if !result.success? && failfast?
149
148
  end
150
149
 
151
150
  def call_test_case_target
@@ -2,7 +2,7 @@ module Webspicy
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 20
5
- TINY = 14
5
+ TINY = 18
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
@@ -0,0 +1,8 @@
1
+ require "webspicy"
2
+ require "webspicy/web"
3
+ require "webspicy/web/inferer"
4
+ require 'logger'
5
+ require 'rack'
6
+ config = Webspicy::Configuration.dress(Path("/formalspec/"))
7
+ use Rack::CommonLogger, Logger.new(STDOUT)
8
+ run Webspicy::Web::Inferer.new(config)
@@ -0,0 +1,95 @@
1
+ require 'rack/proxy'
2
+ module Webspicy
3
+ module Web
4
+ class Inferer < Rack::Proxy
5
+
6
+ def initialize(config, options = nil)
7
+ @webspicy_config = config
8
+ @webspicy_options = options || options_from_env
9
+ super(proxy_options)
10
+ end
11
+ attr_reader :webspicy_config, :webspicy_options
12
+
13
+ def rewrite_env(env)
14
+ env = env.merge(static_env)
15
+ env = handle_path_info(env)
16
+ env
17
+ end
18
+
19
+ def rewrite_response(triplet)
20
+ triplet
21
+ end
22
+
23
+ protected
24
+
25
+ def options_from_env
26
+ {
27
+ target_endpoint: ENV['PROXY_TARGET_ENDPOINT'] || config.host
28
+ }
29
+ end
30
+
31
+ def proxy_options
32
+ uri = target_uri
33
+ backend = "#{uri.scheme}://#{uri.host}"
34
+ backend = "#{backend}:#{uri.port}" if uri.port != 80 && uri.port != 443
35
+ {
36
+ streaming: false,
37
+ backend: backend
38
+ }
39
+ end
40
+
41
+ def static_env
42
+ @static_env ||= begin
43
+ e = {}
44
+ e['HTTP_HOST'] = target_uri.host
45
+ e
46
+ end
47
+ end
48
+
49
+ def target_uri
50
+ @target_uri ||= URI.parse(webspicy_options[:target_endpoint])
51
+ end
52
+
53
+ def handle_path_info(env)
54
+ return env if target_uri.path.nil? || target_uri.path.empty?
55
+
56
+ env['PATH_INFO'] = "#{target_uri.path}#{env['PATH_INFO']}"
57
+ env
58
+ end
59
+
60
+ def perform_request(env)
61
+ webspicy_dump_request(env)
62
+ super.tap{|triplet|
63
+ webspicy_dump_response(env, triplet)
64
+ }
65
+ end
66
+
67
+ def webspicy_dump_request(env)
68
+ base_file = webspicy_dump_basefile(env)
69
+ env['rack.input'].rewind
70
+ input = ''
71
+ env['rack.input'].each { |s| input << s }
72
+ base_file.add_ext('.body').write(input)
73
+ env['rack.input'].rewind
74
+ end
75
+
76
+ def webspicy_dump_response(env, triplet)
77
+ base_file = webspicy_dump_basefile(env)
78
+ base_file.add_ext('.env.json').write(
79
+ JSON.pretty_generate(env)
80
+ )
81
+ base_file.add_ext('.triplet.json').write(
82
+ JSON.pretty_generate(triplet)
83
+ )
84
+ end
85
+
86
+ def webspicy_dump_basefile(env)
87
+ path, method = env['PATH_INFO'], env['REQUEST_METHOD'].downcase
88
+ target_folder = (webspicy_config.folder/'inferer'/'dump')/path[1..-1]
89
+ target_folder.mkdir_p
90
+ target_folder/"#{method}.#{Time.now.to_i}"
91
+ end
92
+
93
+ end # class Inferer
94
+ end # module Web
95
+ end # module Webspicy
@@ -36,19 +36,25 @@ module Webspicy
36
36
 
37
37
  def path_for(specification)
38
38
  {
39
- specification.url => {
39
+ standardize(specification.url) => {
40
40
  summary: specification.name
41
41
  }.merge(verbs_for(specification))
42
42
  }
43
43
  end
44
44
 
45
+ def standardize(url)
46
+ url = url.gsub(/\/$/, '') if url =~ /\/$/
47
+ url
48
+ end
49
+
45
50
  def verbs_for(specification)
46
51
  specification.services.inject({}) do |verbs,service|
47
52
  verb = service.method.downcase
48
53
  verb_defn = {
49
54
  description: service.description,
55
+ parameters: parameters_for(service),
50
56
  responses: responses_for(service)
51
- }
57
+ }.compact
52
58
  unless ["get", "options", "delete", "head"].include?(verb)
53
59
  verb_defn[:requestBody] = request_body_for(service)
54
60
  end
@@ -58,15 +64,29 @@ module Webspicy
58
64
 
59
65
  def request_body_for(service)
60
66
  schema = actual_input_schema(service)
67
+ example = nil # catch(:unfound) { generator.call(schema, {}) }
61
68
  {
62
69
  required: true,
63
70
  content: {
64
71
  "application/json" => {
65
72
  schema: schema.to_json_schema,
66
- example: generator.call(schema, {})
67
- }
73
+ example: example
74
+ }.compact
75
+ }
76
+ }
77
+ end
78
+
79
+ def parameters_for(service)
80
+ schema = actual_input_schema(service)
81
+ params = service.specification.url_placeholders.map{|p|
82
+ {
83
+ in: 'path',
84
+ name: p,
85
+ schema: { type: "string" },
86
+ required: true
68
87
  }
69
88
  }
89
+ params.empty? ? nil : params
70
90
  end
71
91
 
72
92
  def responses_for(service)
@@ -44,7 +44,10 @@ module Webspicy
44
44
  "value": "test <b>test</b> test",
45
45
  "type": "text/html"
46
46
  }
47
- ]
47
+ ],
48
+ "headers": {
49
+ "x-header-key": "personalised-header-value"
50
+ }
48
51
  }
49
52
  J
50
53
 
@@ -58,6 +61,7 @@ module Webspicy
58
61
  expect(subject.cc).to eql(["a-cc-recipient@world.com"])
59
62
  expect(subject.bcc).to eql(["a-bcc-recipient@world.com"])
60
63
  expect(subject.subject).to eql("Hello World")
64
+ expect(subject.headers['x-header-key']).to eql('personalised-header-value')
61
65
  end
62
66
 
63
67
  end
@@ -12,6 +12,7 @@ module Webspicy
12
12
  To: someone@world.com, someoneelse@world.com
13
13
  CC: a-cc-recipient@world.com
14
14
  Subject: Hey world, hello!
15
+ X-Ses-Configuration-Set: SesConfigurationSet
15
16
  Message-ID: <2421bae3-9c42-7988-23b4-b1f6168130c9@webspicy.io>
16
17
  Date: Thu, 24 Jun 2021 13:45:16 +0000
17
18
  MIME-Version: 1.0
@@ -50,11 +51,16 @@ module Webspicy
50
51
  }
51
52
 
52
53
  it 'works as expected' do
53
- expect(subject.from).to eql(["noreply@webspicy.io"])
54
+ expect(subject.from).to eql("noreply@webspicy.io")
54
55
  expect(subject.to).to eql(["someone@world.com", "someoneelse@world.com"])
55
56
  expect(subject.cc).to eql(["a-cc-recipient@world.com"])
56
57
  expect(subject.bcc).to eql(["a-bcc-recipient@world.com"])
57
58
  expect(subject.subject).to eql("Hey world, hello!")
59
+ expect(subject.headers[:from]).to eql("Webspicy <noreply@webspicy.io>")
60
+ expect(subject.headers[:cc]).to eql("a-cc-recipient@world.com")
61
+ expect(subject.headers["message-id"]).to eql("<2421bae3-9c42-7988-23b4-b1f6168130c9@webspicy.io>")
62
+ expect(subject.headers["mime-version"]).to eql("1.0")
63
+ expect(subject.headers["x-ses-configuration-set"]).to eql("SesConfigurationSet")
58
64
  end
59
65
 
60
66
  end
@@ -96,6 +96,10 @@ module Webspicy
96
96
  expect(subject.to).to eql(["someone@world.com", "someoneelse@world.com"])
97
97
  expect(subject.cc).to eql(["a-cc-recipient@world.com"])
98
98
  expect(subject.subject).to eql("Hello World")
99
+ expect(subject.headers[:cc]).to eql("a-cc-recipient@world.com")
100
+ expect(subject.headers[:date]).to eql("Tue, 20 Apr 2021 14:06:13 +0000")
101
+ expect(subject.headers['message-id']).to eql("<607edfd56836e_1b0492af@1d3356d02030.mail>")
102
+ expect(subject.headers['mime-version']).to eql("1.0")
99
103
  end
100
104
 
101
105
  end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+ require 'rack/test'
3
+ require 'webspicy/web'
4
+ require 'webspicy/web/inferer'
5
+ module Webspicy
6
+ module Web
7
+ describe Inferer do
8
+ include Rack::Test::Methods
9
+
10
+ let(:config) {
11
+ Configuration.dress(restful_folder)
12
+ }
13
+
14
+ let(:options) {{
15
+ :target_endpoint => "https://reqres.in/api"
16
+ }}
17
+
18
+ let(:app) {
19
+ Inferer.new(config, options)
20
+ }
21
+
22
+ describe 'proxy_options' do
23
+ it 'works' do
24
+ expect(app.send(:proxy_options)).to eql({
25
+ :streaming => false,
26
+ :backend => "https://reqres.in"
27
+ })
28
+ end
29
+ end
30
+
31
+ describe 'static_env' do
32
+ it 'works' do
33
+ expect(app.send(:static_env)).to eql({
34
+ "HTTP_HOST" => "reqres.in"
35
+ })
36
+ end
37
+ end
38
+
39
+ describe 'the proxy itself' do
40
+ it 'works as expected' do
41
+ get '/users'
42
+ expect(last_response.status).to eql(200)
43
+ expect(last_response.body).not_to be_empty
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ 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.20.14
4
+ version: 0.20.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-25 00:00:00.000000000 Z
11
+ date: 2021-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -226,6 +226,20 @@ dependencies:
226
226
  - - "~>"
227
227
  - !ruby/object:Gem::Version
228
228
  version: '2.7'
229
+ - !ruby/object:Gem::Dependency
230
+ name: rack-proxy
231
+ requirement: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - "~>"
234
+ - !ruby/object:Gem::Version
235
+ version: 0.7.0
236
+ type: :runtime
237
+ prerelease: false
238
+ version_requirements: !ruby/object:Gem::Requirement
239
+ requirements:
240
+ - - "~>"
241
+ - !ruby/object:Gem::Version
242
+ version: 0.7.0
229
243
  description: Webspicy helps testing web services as software operation black boxes
230
244
  email: blambeau@gmail.com
231
245
  executables:
@@ -310,6 +324,8 @@ files:
310
324
  - lib/webspicy/web/client/rack_test_client.rb
311
325
  - lib/webspicy/web/client/support.rb
312
326
  - lib/webspicy/web/formaldoc.fio
327
+ - lib/webspicy/web/inferer.rb
328
+ - lib/webspicy/web/inferer/config.ru
313
329
  - lib/webspicy/web/invocation.rb
314
330
  - lib/webspicy/web/mocker.rb
315
331
  - lib/webspicy/web/mocker/config.ru
@@ -344,6 +360,7 @@ files:
344
360
  - spec/unit/tester/fakesmtp/test_email.rb
345
361
  - spec/unit/tester/test_asserter.rb
346
362
  - spec/unit/tester/test_assertions.rb
363
+ - spec/unit/web/inferer/test_inferer.rb
347
364
  - spec/unit/web/mocker/test_mocker.rb
348
365
  - spec/unit/web/openapi/test_generator.rb
349
366
  - spec/unit/web/specification/test_instantiate_url.rb
@@ -369,7 +386,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
369
386
  - !ruby/object:Gem::Version
370
387
  version: '0'
371
388
  requirements: []
372
- rubygems_version: 3.2.15
389
+ rubygems_version: 3.2.22
373
390
  signing_key:
374
391
  specification_version: 4
375
392
  summary: Webspicy helps testing web services as software operation black boxes!