webspicy 0.20.4 → 0.20.9

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/bin/webspicy +2 -2
  3. data/lib/finitio/webspicy/shared.fio +10 -0
  4. data/lib/webspicy.rb +22 -53
  5. data/lib/webspicy/configuration.rb +3 -1
  6. data/lib/webspicy/configuration/scope.rb +2 -2
  7. data/lib/webspicy/configuration/single_url.rb +35 -25
  8. data/lib/webspicy/configuration/single_yml_file.rb +7 -2
  9. data/lib/webspicy/specification.rb +5 -56
  10. data/lib/webspicy/specification/service.rb +1 -5
  11. data/lib/webspicy/specification/test_case.rb +0 -49
  12. data/lib/webspicy/support/colorize.rb +1 -1
  13. data/lib/webspicy/tester.rb +5 -3
  14. data/lib/webspicy/tester/fakesmtp.rb +1 -1
  15. data/lib/webspicy/tester/fakesmtp/email.rb +13 -0
  16. data/lib/webspicy/tester/file_checker.rb +1 -1
  17. data/lib/webspicy/tester/reporter.rb +2 -1
  18. data/lib/webspicy/tester/reporter/documentation.rb +11 -5
  19. data/lib/webspicy/tester/reporter/exceptions.rb +3 -1
  20. data/lib/webspicy/tester/reporter/junit_xml_file.rb +151 -0
  21. data/lib/webspicy/tester/reporter/progress.rb +1 -1
  22. data/lib/webspicy/tester/reporter/success_or_not.rb +14 -0
  23. data/lib/webspicy/tester/reporter/summary.rb +6 -2
  24. data/lib/webspicy/tester/result.rb +1 -0
  25. data/lib/webspicy/version.rb +1 -1
  26. data/lib/webspicy/web.rb +46 -0
  27. data/lib/webspicy/{formaldoc.fio → web/formaldoc.fio} +5 -13
  28. data/lib/webspicy/web/specification.rb +68 -0
  29. data/lib/webspicy/web/specification/file_upload.rb +39 -0
  30. data/lib/webspicy/web/specification/service.rb +13 -0
  31. data/lib/webspicy/web/specification/test_case.rb +58 -0
  32. data/spec/unit/configuration/scope/test_expand_example.rb +11 -5
  33. data/spec/unit/specification/pre/test_global_request_headers.rb +3 -3
  34. data/spec/unit/specification/service/test_dress_params.rb +2 -2
  35. data/spec/unit/test_configuration.rb +1 -0
  36. data/spec/unit/tester/fakesmtp/test_email.rb +93 -0
  37. data/spec/unit/web/specification/test_instantiate_url.rb +36 -0
  38. data/spec/unit/web/specification/test_url_placeholders.rb +23 -0
  39. data/tasks/test.rake +5 -1
  40. metadata +40 -23
  41. data/lib/webspicy/specification/file_upload.rb +0 -37
  42. data/lib/webspicy/tester/reporter/error_count.rb +0 -29
  43. data/spec/blackbox/commandline.yml +0 -24
  44. data/spec/blackbox/fixtures/passing/config.rb +0 -9
  45. data/spec/blackbox/fixtures/passing/formaldef/get.yml +0 -30
  46. data/spec/unit/specification/test_instantiate_url.rb +0 -34
  47. 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: 9afe697a47ba4391d2e059f1bf3707c04f97f9d6fd50557104a59c6602dbd75c
4
- data.tar.gz: 66ec4036f8e76dad7af0f8b0cf83ea139a67a7b1020aa0a304c26fdc9402d593
3
+ metadata.gz: 0bdf5cfac3023b3a121368cd16c4b36df8cc212b6093672c836fbb2c392e5d68
4
+ data.tar.gz: 3506d6e9ec23a6d21299dcabf2564b1d643a49cf58ba853d6263763838d8efe7
5
5
  SHA512:
6
- metadata.gz: 79feb96443a47523b38f16e4cf7e7edfcd675f5a71c6b33aa452ad452aeacd5e64de1ce1ffa9ff3f5bf9cf428d59dc183e8f1455e1ce26126f2eddf9a14795fb
7
- data.tar.gz: 2761eb20d67f4c697dedf7c27496cfd36ceed4f988f1f54f17809358e570102f1e40c29c47e46f614671504dcf1c877ce2fe6ccb7a72b510994a9da95bb74de1
6
+ metadata.gz: 4c84f0fde9c02350d61969503fd93fa139dc2b39bd377f800597adfae760bfb60b25a83894bac2642b75029c67963a3293a463eed4c00eb85491920a8bd53af4
7
+ data.tar.gz: f215620b9e9a0b7346c09b1ef1a1d1e3acac1f28f57df64ea0864156ceb9e9a7a888bddb4b67462255efc1a15f9860af368fbe510f148ea09871526e90da79fa
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|
@@ -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
@@ -39,6 +39,7 @@ module Webspicy
39
39
  :success => :green
40
40
  }
41
41
  @colorize = true
42
+ @factory = Webspicy::Web
42
43
  @scope_factory = ->(config){ Scope.new(config) }
43
44
  @client = Web::HttpClient
44
45
  @reporter = default_reporter
@@ -109,6 +110,7 @@ module Webspicy
109
110
  end
110
111
  end
111
112
 
113
+ attr_accessor :factory
112
114
  attr_accessor :scope_factory
113
115
 
114
116
  def factor_scope
@@ -445,7 +447,7 @@ module Webspicy
445
447
  @reporter << Tester::Reporter::Documentation.new
446
448
  @reporter << Tester::Reporter::Exceptions.new
447
449
  @reporter << Tester::Reporter::Summary.new
448
- @reporter << Tester::Reporter::ErrorCount.new
450
+ @reporter << Tester::Reporter::SuccessOrNot.new
449
451
  end
450
452
  attr_accessor :reporter
451
453
 
@@ -35,7 +35,7 @@ module Webspicy
35
35
  def each_specification(apply_filter = true, &bl)
36
36
  return enum_for(:each_specification, apply_filter) unless block_given?
37
37
  each_specification_file(apply_filter) do |file, folder|
38
- yield Webspicy.specification(file.load, file, self)
38
+ yield config.factory.specification(file.load, file, self)
39
39
  end
40
40
  end
41
41
 
@@ -138,7 +138,7 @@ module Webspicy
138
138
  return example unless service.default_example
139
139
  h1 = service.default_example.to_info
140
140
  h2 = example.to_info
141
- ex = Specification::TestCase.new(merge_maps(h1, h2))
141
+ ex = config.factory.test_case(merge_maps(h1, h2), self)
142
142
  ex.bind(service, example.counterexample?)
143
143
  end
144
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,25 +10,14 @@ 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
31
16
 
17
+ def relative_location
18
+ @location && @location.relative_to(config.folder)
19
+ end
20
+
32
21
  def locate(relative_path)
33
22
  file = @location.parent/relative_path
34
23
  raise "File not found: #{file}" unless file.exists?
@@ -36,54 +25,15 @@ module Webspicy
36
25
  end
37
26
 
38
27
  def name
39
- @raw[:name]
40
- end
41
-
42
- def url
43
- @raw[:url]
44
- end
45
-
46
- def url_pattern
47
- @url_pattern ||= Mustermann.new(url, type: :template)
28
+ @raw[:name] || relative_location || "Unnamed"
48
29
  end
49
30
 
50
31
  def services
51
32
  @raw[:services] || []
52
33
  end
53
34
 
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
35
  private
72
36
 
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
37
  def bind_services
88
38
  services.each do |s|
89
39
  s.specification = self
@@ -99,4 +49,3 @@ require_relative 'specification/post'
99
49
  require_relative 'specification/err'
100
50
  require_relative 'specification/oldies'
101
51
  require_relative 'specification/test_case'
102
- require_relative 'specification/file_upload'
@@ -21,10 +21,6 @@ module Webspicy
21
21
  specification.config
22
22
  end
23
23
 
24
- def method
25
- @raw[:method]
26
- end
27
-
28
24
  def description
29
25
  @raw[:description]
30
26
  end
@@ -68,7 +64,7 @@ module Webspicy
68
64
  def generated_counterexamples
69
65
  preconditions.map{|pre|
70
66
  pre.counterexamples(self).map{|tc|
71
- tc = Webspicy.test_case(tc, Webspicy.current_scope)
67
+ tc = config.factory.test_case(tc, Webspicy.current_scope)
72
68
  tc.bind(self, true)
73
69
  }
74
70
  }.flatten
@@ -43,10 +43,6 @@ module Webspicy
43
43
  @raw[:seeds]
44
44
  end
45
45
 
46
- def headers
47
- @raw[:headers] ||= {}
48
- end
49
-
50
46
  def metadata
51
47
  @raw[:metadata] ||= {}
52
48
  end
@@ -55,47 +51,10 @@ module Webspicy
55
51
  @raw[:tags] ||= []
56
52
  end
57
53
 
58
- def dress_params
59
- @raw.fetch(:dress_params){ true }
60
- end
61
- alias :dress_params? :dress_params
62
-
63
- def params
64
- @raw[:params] || {}
65
- end
66
-
67
- def body
68
- @raw[:body]
69
- end
70
-
71
- def file_upload
72
- @raw[:file_upload]
73
- end
74
-
75
- def located_file_upload
76
- file_upload ? file_upload.locate(specification) : nil
77
- end
78
-
79
54
  def expected
80
55
  @raw[:expected] || {}
81
56
  end
82
57
 
83
- def expected_content_type
84
- expected[:content_type]
85
- end
86
-
87
- def expected_status
88
- expected[:status]
89
- end
90
-
91
- def is_expected_status?(status)
92
- expected_status === status
93
- end
94
-
95
- def has_expected_status?
96
- not expected[:status].nil?
97
- end
98
-
99
58
  def expected_error
100
59
  expected[:error]
101
60
  end
@@ -104,14 +63,6 @@ module Webspicy
104
63
  !expected_error.nil?
105
64
  end
106
65
 
107
- def expected_headers
108
- expected[:headers] || {}
109
- end
110
-
111
- def has_expected_headers?
112
- !expected_headers.empty?
113
- end
114
-
115
66
  def assert
116
67
  @raw[:assert] || []
117
68
  end