webspicy 0.20.4 → 0.20.9

Sign up to get free protection for your applications and to get access to all the features.
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