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
@@ -5,7 +5,7 @@ module Webspicy
5
5
  def colorize(str, kind, config = nil)
6
6
  return str if config && !config.colorize
7
7
  color = (config || self.config).colors[kind]
8
- ColorizedString[str].colorize(color)
8
+ Paint[str, color]
9
9
  end
10
10
  module_function :colorize
11
11
 
@@ -38,12 +38,12 @@ module Webspicy
38
38
  rescue FailFast
39
39
  end
40
40
  reporter.report
41
- reporter.find(Reporter::ErrorCount).report
41
+ reporter.find(Reporter::SuccessOrNot).report
42
42
  end
43
43
 
44
44
  def call!
45
45
  res = call
46
- abort("KO") unless res == 0
46
+ abort("KO") unless reporter.find(Reporter::SuccessOrNot).success?
47
47
  end
48
48
 
49
49
  def find_and_call(method, url, mutation)
@@ -98,7 +98,7 @@ module Webspicy
98
98
  def load_specification(spec_file)
99
99
  @spec_file = spec_file
100
100
  reporter.before_spec_file
101
- Webspicy.specification(spec_file.load, spec_file, scope)
101
+ config.factory.specification(spec_file.load, spec_file, scope)
102
102
  rescue *PASSTHROUGH_EXCEPTIONS
103
103
  raise
104
104
  rescue Exception => e
@@ -149,6 +149,8 @@ module Webspicy
149
149
  end
150
150
 
151
151
  def call_test_case_target
152
+ @invocation = nil
153
+ @invocation_error = nil
152
154
  reporter.before_invocation
153
155
  @invocation = client.call(test_case)
154
156
  reporter.invocation_done
@@ -30,7 +30,7 @@ module Webspicy
30
30
  end
31
31
 
32
32
  def last_email
33
- emails.last
33
+ emails.first
34
34
  end
35
35
 
36
36
  end # class Fakesmtp
@@ -21,6 +21,19 @@ module Webspicy
21
21
  .map{|h| h["line"][/To:\s*(.*)$/, 1] }
22
22
  end
23
23
 
24
+ def reply_to
25
+ @reply_to ||= data["headerLines"]
26
+ .select{|h| h["key"] == "reply-to" }
27
+ .map{|h| h["line"][/Reply-To:\s*(.*)$/, 1] }
28
+ end
29
+
30
+ def subject
31
+ @subject ||= data["headerLines"]
32
+ .select{|h| h["key"] == "subject" }
33
+ .map{|h| h["line"][/Subject:\s*(.*)$/, 1] }
34
+ .first
35
+ end
36
+
24
37
  end # class Email
25
38
  end # class Fakesmtp
26
39
  end # class Tester
@@ -7,7 +7,7 @@ module Webspicy
7
7
  @reporter << Reporter::FileProgress.new
8
8
  @reporter << Reporter::Exceptions.new
9
9
  @reporter << Reporter::FileSummary.new
10
- @reporter << Reporter::ErrorCount.new
10
+ @reporter << Reporter::SuccessOrNot.new
11
11
  end
12
12
 
13
13
  def run_scope
@@ -80,7 +80,6 @@ module Webspicy
80
80
  end # class Reporter
81
81
  end # class Tester
82
82
  end # module Webspicy
83
- require_relative 'reporter/error_count'
84
83
  require_relative 'reporter/progress'
85
84
  require_relative 'reporter/summary'
86
85
  require_relative 'reporter/documentation'
@@ -88,3 +87,5 @@ require_relative 'reporter/exceptions'
88
87
  require_relative 'reporter/composite'
89
88
  require_relative 'reporter/file_progress'
90
89
  require_relative 'reporter/file_summary'
90
+ require_relative 'reporter/success_or_not'
91
+ require_relative 'reporter/junit_xml_file'
@@ -7,8 +7,10 @@ module Webspicy
7
7
  INDENT = " ".freeze
8
8
 
9
9
  def spec_file_line(spec_file)
10
- relative_path = Path(spec_file).relative_to(config.folder)
11
- colorize_section(">> #{relative_path}", config)
10
+ path = Path(spec_file).expand_path
11
+ path = path.relative_to(config.folder)
12
+ path = spec_file if path.to_s.start_with?(".")
13
+ colorize_section(">> #{path}", config)
12
14
  end
13
15
 
14
16
  def spec_file_error_line(spec_file, ex)
@@ -49,12 +51,16 @@ module Webspicy
49
51
  end
50
52
 
51
53
  def before_service
52
- io.puts spec_file_line(spec_file)
53
- io.puts
54
- io.flush
54
+ @spec_file_line_printed = false
55
55
  end
56
56
 
57
57
  def before_test_case
58
+ unless @spec_file_line_printed
59
+ io.puts spec_file_line(spec_file)
60
+ io.puts
61
+ io.flush
62
+ @spec_file_line_printed = true
63
+ end
58
64
  io.puts service_line(service, test_case)
59
65
  io.flush
60
66
  end
@@ -15,7 +15,7 @@ module Webspicy
15
15
  @spec_file_errors << spec_file_error_line(spec_file, e)
16
16
  end
17
17
 
18
- def after_each_done
18
+ def test_case_done
19
19
  @failed_results << result unless result.success?
20
20
  end
21
21
 
@@ -24,6 +24,8 @@ module Webspicy
24
24
  report_failed_results
25
25
  end
26
26
 
27
+ private
28
+
27
29
  def report_spec_file_errors
28
30
  return if spec_file_errors.empty?
29
31
  io.puts
@@ -0,0 +1,151 @@
1
+ module Webspicy
2
+ class Tester
3
+ class Reporter
4
+ class JunitXmlFile < Reporter
5
+
6
+ TPL = <<~XML
7
+ <?xml version="1.0" encoding="UTF-8"?>
8
+ <testsuites
9
+ disabled="{{counts.disabled}}"
10
+ errors="{{counts.errors}}"
11
+ failures="{{counts.failures}}"
12
+ tests="{{counts.total}}"
13
+ time="{{time}}s"
14
+ >
15
+ {{#testsuites}}
16
+ <testsuite
17
+ name="{{name}}"
18
+ tests="{{counts.total}}"
19
+ errors="{{counts.errors}}"
20
+ failures="{{counts.failures}}"
21
+ time="{{time}}s"
22
+ >
23
+ {{#testcases}}
24
+ <testcase
25
+ name="{{name}}"
26
+ assertions="{{assert}}"
27
+ classname="{{classname}}"
28
+ status=""
29
+ time="{{time}}s"
30
+ >
31
+ {{#errors}}
32
+ <error
33
+ message="{{message}}"
34
+ type="{{type}}"
35
+ ></error>
36
+ {{/errors}}
37
+ {{#failures}}
38
+ <failure
39
+ message="{{message}}"
40
+ type="{{type}}"
41
+ ></failure>
42
+ {{/failures}}
43
+ </testcase>
44
+ {{/testcases}}
45
+ </testsuite>
46
+ {{/testsuites}}
47
+ </testsuites>
48
+ XML
49
+
50
+ def initialize(path_or_io = STDOUT)
51
+ @path_or_io = path_or_io
52
+ path_or_io.parent.mkdir_p if path_or_io.is_a?(Path)
53
+ end
54
+
55
+ attr_reader :template_data, :timer_all, :timer_specification, :timer_testcase
56
+
57
+ def before_all
58
+ @timer_all = Time.now
59
+ @template_data = OpenStruct.new({
60
+ counts: Hash.new{|h,k| h[k] = 0 },
61
+ testsuites: []
62
+ })
63
+ end
64
+
65
+ def after_all
66
+ template_data.time = Time.now - timer_all
67
+ end
68
+
69
+ def before_specification
70
+ @timer_specification = Time.now
71
+ template_data.testsuites << OpenStruct.new({
72
+ :name => specification.name,
73
+ :counts => Hash.new{|h,k| h[k] = 0 },
74
+ :testcases => []
75
+ })
76
+ end
77
+
78
+ def specification_done
79
+ template_data.testsuites[-1].time = Time.now - timer_specification
80
+ end
81
+
82
+ def spec_file_error(e)
83
+ template_data.testsuites[-1].testcases << OpenStruct.new({
84
+ :name => "Specification can be loaded",
85
+ :assert => 1,
86
+ :classname => "Webspicy.Specification",
87
+ :failures => [],
88
+ :errors => [OpenStruct.new({
89
+ :type => e.class,
90
+ :message => e.message
91
+ })]
92
+ })
93
+ end
94
+
95
+ def before_test_case
96
+ @timer_testcase = Time.now
97
+ template_data.testsuites[-1].testcases << OpenStruct.new({
98
+ :name => test_case.description,
99
+ :assert => test_case.assert.length,
100
+ :classname => test_case.class.name.to_s.gsub(/::/, "."),
101
+ :failures => [],
102
+ :errors => [],
103
+ })
104
+ template_data.counts[:total] += 1
105
+ template_data.testsuites[-1].counts[:total] += 1
106
+ end
107
+
108
+ def test_case_done
109
+ template_data.testsuites[-1].testcases[-1].time = Time.now - timer_testcase
110
+ end
111
+
112
+ def check_failure(check, ex)
113
+ template_data.testsuites[-1].testcases[-1].failures << OpenStruct.new({
114
+ :type => check.class.name,
115
+ :message => ex.message
116
+ })
117
+ template_data.counts[:failures] += 1
118
+ template_data.testsuites[-1].counts[:failures] += 1
119
+ end
120
+
121
+ def check_error(check, ex)
122
+ template_data.testsuites[-1].testcases[-1].errors << OpenStruct.new({
123
+ :type => check.class.name,
124
+ :message => ex.message
125
+ })
126
+ template_data.counts[:errors] += 1
127
+ template_data.testsuites[-1].counts[:errors] += 1
128
+ end
129
+
130
+ def report
131
+ require 'mustache'
132
+ with_io do |io|
133
+ io << Mustache.render(TPL, template_data)
134
+ end
135
+ end
136
+
137
+ private
138
+
139
+ def with_io(&bl)
140
+ case io = @path_or_io
141
+ when IO, StringIO
142
+ bl.call(io)
143
+ else
144
+ Path(io).open('w', &bl)
145
+ end
146
+ end
147
+
148
+ end # class JunitXmlFile
149
+ end # class Reporter
150
+ end # class Tester
151
+ end # module Webspicy
@@ -7,7 +7,7 @@ module Webspicy
7
7
  io.print colorize_error("X", config)
8
8
  end
9
9
 
10
- def after_each_done
10
+ def test_case_done
11
11
  if result.success?
12
12
  io.print colorize_success(".", config)
13
13
  elsif result.failure?
@@ -0,0 +1,14 @@
1
+ module Webspicy
2
+ class Tester
3
+ class Reporter
4
+ class SuccessOrNot < Summary
5
+
6
+ def report
7
+ total_error_count
8
+ end
9
+
10
+ end # class SuccessOrNot
11
+ ErrorCount = SuccessOrNot # for backward compatibility
12
+ end # class Reporter
13
+ end # class Tester
14
+ end # module Webspicy
@@ -26,7 +26,7 @@ module Webspicy
26
26
  @spec_file_errors_count += 1
27
27
  end
28
28
 
29
- def after_each_done
29
+ def test_case_done
30
30
  if tester.test_case.counterexample?
31
31
  @counterexamples_count += 1
32
32
  else
@@ -54,8 +54,12 @@ module Webspicy
54
54
  io.flush
55
55
  end
56
56
 
57
+ def total_error_count
58
+ @spec_file_errors_count + @errors_count + @failures_count
59
+ end
60
+
57
61
  def success?
58
- @spec_file_errors_count == 0 && @errors_count == 0 && @failures_count == 0
62
+ total_error_count == 0
59
63
  end
60
64
 
61
65
  end # class Summary
@@ -18,6 +18,7 @@ module Webspicy
18
18
  check!
19
19
  else
20
20
  @errors << [InvocationSuceeded.new(self), tester.invocation_error]
21
+ reporter.check_error(*errors.first)
21
22
  end
22
23
  end
23
24
  attr_reader :tester, :scope, :client
@@ -2,7 +2,7 @@ module Webspicy
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 20
5
- TINY = 4
5
+ TINY = 9
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
data/lib/webspicy/web.rb CHANGED
@@ -1,3 +1,49 @@
1
+ module Webspicy
2
+ module Web
3
+
4
+ require_relative 'web/specification'
5
+
6
+ FORMALDOC = Finitio.system(Path.dir/("web/formaldoc.fio"))
7
+
8
+ def specification(raw, file = nil, scope = Webspicy.default_scope)
9
+ raw = YAML.load(raw) if raw.is_a?(String)
10
+ Webspicy.with_scope(scope) do
11
+ r = FORMALDOC["Specification"].dress(raw)
12
+ r.config = scope.config
13
+ r.located_at!(file) if file
14
+ r
15
+ end
16
+ rescue Finitio::Error => ex
17
+ handle_finitio_error(ex)
18
+ end
19
+ module_function :specification
20
+
21
+ def service(raw, scope = Webspicy.default_scope)
22
+ Webspicy.with_scope(scope) do
23
+ FORMALDOC["Service"].dress(raw)
24
+ end
25
+ rescue Finitio::Error => ex
26
+ handle_finitio_error(ex)
27
+ end
28
+ module_function :service
29
+
30
+ def test_case(raw, scope = Webspicy.default_scope)
31
+ Webspicy.with_scope(scope) do
32
+ FORMALDOC["TestCase"].dress(raw)
33
+ end
34
+ rescue Finitio::Error => ex
35
+ handle_finitio_error(ex)
36
+ end
37
+ module_function :test_case
38
+
39
+ def handle_finitio_error(ex)
40
+ puts ex.root_cause.message
41
+ raise ex
42
+ end
43
+ module_function :handle_finitio_error
44
+
45
+ end # module Web
46
+ end # module Webspicy
1
47
  require_relative 'web/client'
2
48
  require_relative 'web/invocation'
3
49
  require_relative 'web/mocker'
@@ -1,23 +1,17 @@
1
1
  @import finitio/data
2
+ @import webspicy/shared
2
3
 
3
4
  Method =
4
5
  String( s | s =~ /^(GET|POST|POST_FORM|PUT|DELETE|PATCH|PUT|OPTIONS)$/ )
5
6
 
6
- Tag = String( s | s.length > 0 )
7
-
8
- Schema =
9
- .Finitio::System <fio> String
10
- \( s | ::Webspicy.schema(s) )
11
- \( s | raise "Unsupported" )
12
-
13
7
  FileUpload =
14
- .Webspicy::FileUpload <info> {
8
+ .Webspicy::Web::Specification::FileUpload <info> {
15
9
  path : String
16
10
  content_type : String
17
11
  param_name :? String
18
12
  }
19
13
 
20
- Specification = .Webspicy::Specification
14
+ Specification = .Webspicy::Web::Specification
21
15
  <info> {
22
16
  name: String
23
17
  url: String
@@ -41,7 +35,7 @@ Specification = .Webspicy::Specification
41
35
  }
42
36
 
43
37
  Service =
44
- .Webspicy::Specification::Service <info> {
38
+ .Webspicy::Web::Specification::Service <info> {
45
39
  method : Method
46
40
  description : String
47
41
  preconditions :? [String]|String
@@ -57,7 +51,7 @@ Service =
57
51
  }
58
52
 
59
53
  TestCase =
60
- .Webspicy::Specification::TestCase <info> {
54
+ .Webspicy::Web::Specification::TestCase <info> {
61
55
  description :? String
62
56
  dress_params :? Boolean
63
57
  params :? Params
@@ -77,8 +71,6 @@ TestCase =
77
71
  tags :? [Tag]
78
72
  }
79
73
 
80
- Params = .Array|.Hash
81
-
82
74
  StatusRange = .Webspicy::Support::StatusRange
83
75
  <int> Integer
84
76
  <str> String(s | s =~ /^\dxx$/ )