webspicy 0.20.0 → 0.20.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/bin/sandr +14 -0
  3. data/bin/search +2 -0
  4. data/bin/webspicy +3 -4
  5. data/lib/finitio/webspicy/shared.fio +10 -0
  6. data/lib/webspicy.rb +22 -53
  7. data/lib/webspicy/configuration.rb +17 -0
  8. data/lib/webspicy/configuration/scope.rb +3 -2
  9. data/lib/webspicy/configuration/single_url.rb +35 -25
  10. data/lib/webspicy/configuration/single_yml_file.rb +7 -2
  11. data/lib/webspicy/specification.rb +0 -55
  12. data/lib/webspicy/specification/oldies/bridge.rb +4 -1
  13. data/lib/webspicy/specification/post/missing_condition_impl.rb +2 -2
  14. data/lib/webspicy/specification/post/unexpected_condition_impl.rb +2 -2
  15. data/lib/webspicy/specification/service.rb +4 -5
  16. data/lib/webspicy/specification/test_case.rb +3 -49
  17. data/lib/webspicy/support/colorize.rb +7 -1
  18. data/lib/webspicy/tester.rb +21 -20
  19. data/lib/webspicy/tester/assertions.rb +2 -2
  20. data/lib/webspicy/tester/reporter.rb +5 -0
  21. data/lib/webspicy/tester/reporter/documentation.rb +26 -8
  22. data/lib/webspicy/tester/reporter/error_count.rb +11 -7
  23. data/lib/webspicy/tester/reporter/file_progress.rb +2 -2
  24. data/lib/webspicy/tester/reporter/file_summary.rb +2 -2
  25. data/lib/webspicy/tester/reporter/progress.rb +4 -4
  26. data/lib/webspicy/tester/reporter/summary.rb +8 -7
  27. data/lib/webspicy/tester/result.rb +2 -2
  28. data/lib/webspicy/tester/result/errcondition_met.rb +1 -3
  29. data/lib/webspicy/tester/result/error_schema_met.rb +1 -0
  30. data/lib/webspicy/tester/result/output_schema_met.rb +1 -0
  31. data/lib/webspicy/tester/result/postcondition_met.rb +1 -3
  32. data/lib/webspicy/version.rb +1 -1
  33. data/lib/webspicy/web.rb +46 -0
  34. data/lib/webspicy/{formaldoc.fio → web/formaldoc.fio} +5 -13
  35. data/lib/webspicy/web/invocation.rb +7 -3
  36. data/lib/webspicy/web/specification.rb +68 -0
  37. data/lib/webspicy/web/specification/file_upload.rb +39 -0
  38. data/lib/webspicy/web/specification/service.rb +13 -0
  39. data/lib/webspicy/web/specification/test_case.rb +58 -0
  40. data/spec/unit/configuration/scope/test_expand_example.rb +11 -5
  41. data/spec/unit/specification/pre/test_global_request_headers.rb +3 -3
  42. data/spec/unit/specification/service/test_dress_params.rb +2 -2
  43. data/spec/unit/test_configuration.rb +1 -0
  44. data/spec/unit/web/specification/test_instantiate_url.rb +36 -0
  45. data/spec/unit/web/specification/test_url_placeholders.rb +23 -0
  46. data/tasks/test.rake +2 -1
  47. metadata +24 -16
  48. data/lib/webspicy/specification/file_upload.rb +0 -37
  49. data/spec/unit/specification/test_instantiate_url.rb +0 -34
  50. data/spec/unit/specification/test_url_placeholders.rb +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d0bfd23b321b3e1216316e09c2b9e2d761a9e3179c62830d4b6a99b13042f4cc
4
- data.tar.gz: 0661ba60f10ac2433bb5952d3c17141d880363e1d0c763836877a08b9673a8d1
3
+ metadata.gz: cf642b32d3e6abe3f90e53c047b8e1e973910041133ba4626d9ba7c2cb5ba333
4
+ data.tar.gz: 95860fd2e93a11f5dcecf7e175371eee6378e073ee60e22ea266c44e69265d19
5
5
  SHA512:
6
- metadata.gz: d276e4fb01cfd084e94917d6987b9e545c8c28edeaa082b55330ac3978f28d3c358e39f9a09ceda6f0aff59e55f9ff0fd989c2f9c247885d78a6d89a7a82f37d
7
- data.tar.gz: bdfa965f896d9167432a8dbb4404720b9f278b590d031f92d8ad44c501be9a03e922a5bb58ae667644de803743210668cde3726ae0b901e6750f07ecb2718011
6
+ metadata.gz: 8415d763e56aec8f101d7140974e1ce959da7b1b0cc405c81c64976481a49b3042b442779973fe1eac76e20d9283e8aa6abb1c1363021c7c79d8f70fae59b482
7
+ data.tar.gz: 8bdfbf03a2c792fb1d772ec2260227ec24b0bfc87f4df5bf70e0baf2376818ed580f43e41d6ef1b4c753e5bc3cc620dcae1479501baea2a5cc84d65ad7370394
data/bin/sandr ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ require 'path'
3
+
4
+ def sandr(file)
5
+ file.write file.read.gsub(ARGV[0], ARGV[1])
6
+ end
7
+
8
+ Path.dir.parent.glob("lib/**/*.rb") do |file|
9
+ sandr(file)
10
+ end
11
+
12
+ Path.dir.parent.glob("spec/**/*.rb") do |file|
13
+ sandr(file)
14
+ end
data/bin/search ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ grep -Rn --color $1 lib spec
data/bin/webspicy CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  #/
3
3
  #/ Document & test web services as black-box operations.
4
- #/ (c) Enspirit SRL. Distributed under MIT licence.
4
+ #/ Webspicy vVERSION, (c) Enspirit SRL. Distributed under MIT licence.
5
5
  #/
6
6
  #/ Usage: webspicy [options] URL # run default test againt url
7
7
  #/ Usage: webspicy [options] path/to/config.rb # run whole test suite
@@ -28,7 +28,7 @@ require 'optparse'
28
28
 
29
29
  def showhelp
30
30
  file = __FILE__
31
- exec "grep ^#/<'#{file}'|cut -c4-"
31
+ exec "grep ^#/<'#{file}'|cut -c4-|sed s/VERSION/#{Webspicy::VERSION}/g"
32
32
  end
33
33
 
34
34
  ARGV.options do |opts|
@@ -55,5 +55,4 @@ if ARGV.size != 1
55
55
  end
56
56
 
57
57
  config = Webspicy::Configuration.dress(ARGV[0])
58
- res = Webspicy::Tester.new(config).call
59
- abort("#{res} errors occured") unless res == 0
58
+ Webspicy::Tester.new(config).call!
@@ -0,0 +1,10 @@
1
+ @import finitio/data
2
+
3
+ Tag = String( s | s.length > 0 )
4
+
5
+ Schema =
6
+ .Finitio::System <fio> String
7
+ \( s | ::Webspicy.schema(s) )
8
+ \( s | raise "Unsupported" )
9
+
10
+ Params = .Array|.Hash
data/lib/webspicy.rb CHANGED
@@ -7,7 +7,7 @@ require 'ostruct'
7
7
  require 'yaml'
8
8
  require 'rack/test'
9
9
  require 'mustermann'
10
- require 'colorized_string'
10
+ require 'paint'
11
11
  require 'securerandom'
12
12
  require 'forwardable'
13
13
  module Webspicy
@@ -21,22 +21,10 @@ module Webspicy
21
21
  require 'webspicy/specification'
22
22
  require 'webspicy/configuration'
23
23
  require 'webspicy/tester'
24
- require 'webspicy/web'
25
24
 
26
25
  class Error < StandardError; end
27
26
  class TimeoutError < Error; end
28
27
 
29
- ###
30
- ### Backward compatibility
31
- ###
32
- Client = Tester::Client
33
- HttpClient = Web::HttpClient
34
- RackTestClient = Web::RackTestClient
35
- Resource = Specification
36
- FileUpload = Specification::FileUpload
37
- Scope = Configuration::Scope
38
- Checker = Tester::FileChecker
39
-
40
28
  ###
41
29
  ### About folders
42
30
  ###
@@ -49,10 +37,11 @@ module Webspicy
49
37
  ### About formal doc and specifications defined there
50
38
  ###
51
39
  Finitio.stdlib_path(Path.dir/"finitio")
40
+
52
41
  DEFAULT_SYSTEM = Finitio.system(<<~FIO)
53
42
  @import webspicy/scalars
54
43
  FIO
55
- FORMALDOC = Finitio.system(Path.dir/("webspicy/formaldoc.fio"))
44
+
56
45
 
57
46
  ###
58
47
  ### Exceptions that we let pass during testing
@@ -66,45 +55,6 @@ module Webspicy
66
55
  end
67
56
  module_function :default_scope
68
57
 
69
- def specification(raw, file = nil, scope = default_scope)
70
- raw = YAML.load(raw) if raw.is_a?(String)
71
- with_scope(scope) do
72
- r = FORMALDOC["Specification"].dress(raw)
73
- r.config = scope.config
74
- r.located_at!(file) if file
75
- r
76
- end
77
- rescue Finitio::Error => ex
78
- handle_finitio_error(ex, scope)
79
- end
80
- module_function :specification
81
-
82
- def service(raw, scope = default_scope)
83
- with_scope(scope) do
84
- FORMALDOC["Service"].dress(raw)
85
- end
86
- rescue Finitio::Error => ex
87
- handle_finitio_error(ex)
88
- end
89
- module_function :service
90
-
91
- def test_case(raw, scope = default_scope)
92
- with_scope(scope) do
93
- FORMALDOC["TestCase"].dress(raw)
94
- end
95
- rescue Finitio::Error => ex
96
- handle_finitio_error(ex)
97
- end
98
- module_function :test_case
99
-
100
- def handle_finitio_error(ex, scope)
101
- # msg = "#{ex.message}:\n #{ex.root_cause.message}"
102
- # msg = Support::Colorize.colorize_error(msg, scope.config)
103
- # fatal(msg)
104
- raise
105
- end
106
- module_function :handle_finitio_error
107
-
108
58
  #
109
59
  # Yields the block after having installed `scope` globally.
110
60
  #
@@ -185,4 +135,23 @@ module Webspicy
185
135
  end
186
136
  module_function :fatal
187
137
 
138
+ require 'webspicy/web'
139
+
140
+ ###
141
+ ### Backward compatibility
142
+ ###
143
+ Client = Tester::Client
144
+ HttpClient = Web::HttpClient
145
+ RackTestClient = Web::RackTestClient
146
+ Resource = Specification
147
+ FileUpload = Web::Specification::FileUpload
148
+ Scope = Configuration::Scope
149
+ Checker = Tester::FileChecker
150
+
151
+ [:specification, :service, :test_case].each do |meth|
152
+ define_method(meth) do |*args, &bl|
153
+ Webspicy::Web.send(meth, *args, &bl)
154
+ end
155
+ module_function(meth)
156
+ end
188
157
  end
@@ -33,12 +33,16 @@ module Webspicy
33
33
  @service_filter = default_service_filter
34
34
  @test_case_filter = default_test_case_filter
35
35
  @colors = {
36
+ :section => :magenta,
36
37
  :highlight => :cyan,
37
38
  :error => :red,
38
39
  :success => :green
39
40
  }
41
+ @colorize = true
42
+ @factory = Webspicy::Web
40
43
  @scope_factory = ->(config){ Scope.new(config) }
41
44
  @client = Web::HttpClient
45
+ @reporter = default_reporter
42
46
  Path.require_tree(@folder/'support') if (@folder/'support').exists?
43
47
  @world = Support::World.new(folder/'world', self)
44
48
  yield(self) if block_given?
@@ -47,6 +51,8 @@ module Webspicy
47
51
  protected :folder=
48
52
 
49
53
  attr_accessor :colors
54
+ attr_accessor :colorize
55
+
50
56
  attr_reader :world
51
57
 
52
58
  def self.dress(arg, &bl)
@@ -104,6 +110,7 @@ module Webspicy
104
110
  end
105
111
  end
106
112
 
113
+ attr_accessor :factory
107
114
  attr_accessor :scope_factory
108
115
 
109
116
  def factor_scope
@@ -434,6 +441,16 @@ module Webspicy
434
441
  end
435
442
  private :default_rspec_options
436
443
 
444
+ # Returns the default reporter to use.
445
+ def default_reporter
446
+ @reporter = Tester::Reporter::Composite.new
447
+ @reporter << Tester::Reporter::Documentation.new
448
+ @reporter << Tester::Reporter::Exceptions.new
449
+ @reporter << Tester::Reporter::Summary.new
450
+ @reporter << Tester::Reporter::ErrorCount.new
451
+ end
452
+ attr_accessor :reporter
453
+
437
454
  # Returns the Data system to use for parsing schemas
438
455
  #
439
456
  # The data system associated with a configuration is build when the
@@ -23,6 +23,7 @@ module Webspicy
23
23
  folder = config.folder
24
24
  world = config.folder/"world"
25
25
  fs = folder.glob("**/*.yml").reject{|f| f.to_s.start_with?(world.to_s) }
26
+ fs = fs.sort
26
27
  fs = fs.select(&to_filter_proc(config.file_filter)) if apply_filter
27
28
  fs.each do |file|
28
29
  yield file, folder
@@ -34,7 +35,7 @@ module Webspicy
34
35
  def each_specification(apply_filter = true, &bl)
35
36
  return enum_for(:each_specification, apply_filter) unless block_given?
36
37
  each_specification_file(apply_filter) do |file, folder|
37
- yield Webspicy.specification(file.load, file, self)
38
+ yield config.factory.specification(file.load, file, self)
38
39
  end
39
40
  end
40
41
 
@@ -137,7 +138,7 @@ module Webspicy
137
138
  return example unless service.default_example
138
139
  h1 = service.default_example.to_info
139
140
  h2 = example.to_info
140
- ex = Specification::TestCase.new(merge_maps(h1, h2))
141
+ ex = config.factory.test_case(merge_maps(h1, h2), self)
141
142
  ex.bind(service, example.counterexample?)
142
143
  end
143
144
 
@@ -10,37 +10,47 @@ module Webspicy
10
10
  end
11
11
  attr_reader :url
12
12
 
13
- def each_specification(&bl)
13
+ def each_specification_file(*args, &bl)
14
+ return enum_for(:each_specification_file) unless block_given?
15
+ yield Path.tempfile(["specification",".yml"]).tap{|f|
16
+ f.write(specification_src)
17
+ }
18
+ end
19
+
20
+ def each_specification(*args, &bl)
14
21
  return enum_for(:each_specification) unless block_given?
15
- spec = <<~YML
22
+ yield config.factory.specification(specification_src, nil, self)
23
+ end
24
+
25
+ def specification_src
26
+ <<~YML.tap{|s| Webspicy.debug(s) }
16
27
  ---
17
- name: |-
18
- Default specification
28
+ description: |-
29
+ Getting #{url}
30
+
19
31
  url: |-
20
32
  #{url}
21
33
 
22
- services:
23
- - method: |-
24
- GET
25
- description: |-
26
- Getting #{url}
27
-
28
- input_schema: |-
29
- Any
30
- output_schema: |-
31
- Any
32
- error_schema: |-
33
- Any
34
-
35
- examples:
36
- - description: |-
37
- it returns a 200
38
- params: {}
39
- expected:
40
- status: 200
34
+ method: |-
35
+ GET
36
+
37
+ input_schema: |-
38
+ Any
39
+
40
+ output_schema: |-
41
+ Any
42
+
43
+ error_schema: |-
44
+ Any
45
+
46
+ examples:
47
+
48
+ - description: |-
49
+ it returns a 200
50
+ params: {}
51
+ expected:
52
+ status: 200
41
53
  YML
42
- Webspicy.debug(spec)
43
- yield Webspicy.specification(spec, nil, self)
44
54
  end
45
55
 
46
56
  end # class SingleUrlScope
@@ -10,9 +10,14 @@ module Webspicy
10
10
  end
11
11
  attr_reader :file
12
12
 
13
- def each_specification(&bl)
13
+ def each_specification_file(*args, &bl)
14
+ return enum_for(:each_specification_file) unless block_given?
15
+ yield(file)
16
+ end
17
+
18
+ def each_specification(*args, &bl)
14
19
  return enum_for(:each_specification) unless block_given?
15
- yield Webspicy.specification(file.read, nil, self)
20
+ yield config.factory.specification(file.read, nil, self)
16
21
  end
17
22
 
18
23
  end # class SingleYmlFileScope
@@ -10,21 +10,6 @@ module Webspicy
10
10
  attr_accessor :config
11
11
  attr_reader :location
12
12
 
13
- def self.info(raw)
14
- new(raw)
15
- end
16
-
17
- def self.singleservice(raw)
18
- converted = {
19
- name: raw[:name] || "Unamed specification",
20
- url: raw[:url],
21
- services: [
22
- Webspicy.service(raw.reject{|k| k==:url or k==:name }, Webspicy.current_scope)
23
- ]
24
- }
25
- info(converted)
26
- end
27
-
28
13
  def located_at!(location)
29
14
  @location = Path(location)
30
15
  end
@@ -39,51 +24,12 @@ module Webspicy
39
24
  @raw[:name]
40
25
  end
41
26
 
42
- def url
43
- @raw[:url]
44
- end
45
-
46
- def url_pattern
47
- @url_pattern ||= Mustermann.new(url, type: :template)
48
- end
49
-
50
27
  def services
51
28
  @raw[:services] || []
52
29
  end
53
30
 
54
- def url_placeholders
55
- url.scan(/\{([a-zA-Z]+(\.[a-zA-Z]+)*)\}/).map{|x| x.first }
56
- end
57
-
58
- def instantiate_url(params)
59
- url, rest = self.url, params.dup
60
- url_placeholders.each do |placeholder|
61
- value, rest = extract_placeholder_value(rest, placeholder)
62
- url = url.gsub("{#{placeholder}}", value.to_s)
63
- end
64
- [ url, rest ]
65
- end
66
-
67
- def to_singleservice
68
- raise NotImplementedError
69
- end
70
-
71
31
  private
72
32
 
73
- def extract_placeholder_value(params, placeholder, split = nil)
74
- return extract_placeholder_value(params, placeholder, placeholder.split(".")) unless split
75
-
76
- key = [ split.first, split.first.to_sym ].find{|k| params.has_key?(k) }
77
- raise "Missing URL parameter `#{placeholder}`" unless key
78
-
79
- if split.size == 1
80
- [ params[key], params.dup.delete_if{|k| k == key } ]
81
- else
82
- value, rest = extract_placeholder_value(params[key], placeholder, split[1..-1])
83
- [ value, params.merge(key => rest) ]
84
- end
85
- end
86
-
87
33
  def bind_services
88
34
  services.each do |s|
89
35
  s.specification = self
@@ -99,4 +45,3 @@ require_relative 'specification/post'
99
45
  require_relative 'specification/err'
100
46
  require_relative 'specification/oldies'
101
47
  require_relative 'specification/test_case'
102
- require_relative 'specification/file_upload'
@@ -10,11 +10,14 @@ module Webspicy
10
10
  attr_reader :target
11
11
 
12
12
  def instrument
13
+ return unless target.respond_to?(:instrument)
13
14
  target.instrument(test_case, client)
14
15
  end
15
16
 
16
17
  def check!
17
- target.check(invocation)
18
+ return unless target.respond_to?(:check)
19
+ res = target.check(invocation)
20
+ res ? fail!(res) : nil
18
21
  end
19
22
 
20
23
  def to_s