webspicy 0.19.0 → 0.20.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/bin/webspicy +1 -2
  3. data/lib/webspicy.rb +0 -2
  4. data/lib/webspicy/configuration.rb +15 -0
  5. data/lib/webspicy/configuration/scope.rb +1 -0
  6. data/lib/webspicy/specification.rb +4 -3
  7. data/lib/webspicy/specification/condition.rb +29 -4
  8. data/lib/webspicy/specification/err.rb +18 -0
  9. data/lib/webspicy/specification/oldies.rb +4 -0
  10. data/lib/webspicy/specification/oldies/bridge.rb +32 -0
  11. data/lib/webspicy/specification/{errcondition.rb → oldies/errcondition.rb} +5 -0
  12. data/lib/webspicy/specification/{postcondition.rb → oldies/postcondition.rb} +5 -0
  13. data/lib/webspicy/specification/{precondition.rb → oldies/precondition.rb} +5 -2
  14. data/lib/webspicy/specification/post.rb +20 -0
  15. data/lib/webspicy/specification/post/missing_condition_impl.rb +15 -0
  16. data/lib/webspicy/specification/post/unexpected_condition_impl.rb +15 -0
  17. data/lib/webspicy/specification/pre.rb +19 -0
  18. data/lib/webspicy/specification/{precondition → pre}/global_request_headers.rb +4 -4
  19. data/lib/webspicy/specification/{precondition → pre}/robust_to_invalid_input.rb +4 -4
  20. data/lib/webspicy/specification/service.rb +29 -5
  21. data/lib/webspicy/specification/test_case.rb +3 -0
  22. data/lib/webspicy/support.rb +12 -2
  23. data/lib/webspicy/support/colorize.rb +6 -0
  24. data/lib/webspicy/tester.rb +89 -27
  25. data/lib/webspicy/tester/assertions.rb +2 -2
  26. data/lib/webspicy/tester/client.rb +0 -26
  27. data/lib/webspicy/tester/fakeses.rb +41 -0
  28. data/lib/webspicy/tester/fakeses/email.rb +38 -0
  29. data/lib/webspicy/tester/fakesmtp.rb +39 -0
  30. data/lib/webspicy/tester/fakesmtp/email.rb +27 -0
  31. data/lib/webspicy/tester/reporter.rb +5 -0
  32. data/lib/webspicy/tester/reporter/documentation.rb +31 -8
  33. data/lib/webspicy/tester/reporter/error_count.rb +11 -7
  34. data/lib/webspicy/tester/reporter/exceptions.rb +2 -0
  35. data/lib/webspicy/tester/reporter/file_progress.rb +5 -2
  36. data/lib/webspicy/tester/reporter/file_summary.rb +3 -2
  37. data/lib/webspicy/tester/reporter/progress.rb +6 -4
  38. data/lib/webspicy/tester/reporter/summary.rb +9 -7
  39. data/lib/webspicy/tester/result.rb +16 -13
  40. data/lib/webspicy/tester/result/errcondition_met.rb +1 -3
  41. data/lib/webspicy/tester/result/error_schema_met.rb +1 -0
  42. data/lib/webspicy/tester/result/invocation_succeeded.rb +13 -0
  43. data/lib/webspicy/tester/result/output_schema_met.rb +1 -0
  44. data/lib/webspicy/tester/result/postcondition_met.rb +1 -3
  45. data/lib/webspicy/version.rb +2 -2
  46. data/lib/webspicy/web/invocation.rb +7 -3
  47. data/spec/blackbox/commandline.yml +24 -0
  48. data/spec/blackbox/fixtures/passing/config.rb +9 -0
  49. data/spec/blackbox/fixtures/passing/formaldef/get.yml +30 -0
  50. data/spec/unit/specification/{precondition → pre}/test_global_request_headers.rb +9 -4
  51. data/spec/unit/specification/test_condition.rb +18 -0
  52. data/spec/unit/tester/fakeses/test_email.rb +40 -0
  53. data/tasks/test.rake +2 -1
  54. metadata +34 -18
@@ -66,6 +66,11 @@ module Webspicy
66
66
  }
67
67
  end
68
68
 
69
+ def find(kind)
70
+ return self if self.is_a?(kind)
71
+ raise "Missing reporter #{kind}"
72
+ end
73
+
69
74
  protected
70
75
 
71
76
  def plural(word, count)
@@ -4,61 +4,84 @@ module Webspicy
4
4
  class Documentation < Reporter
5
5
 
6
6
  module Helpers
7
+ INDENT = " ".freeze
8
+
9
+ def spec_file_line(spec_file)
10
+ relative_path = Path(spec_file).relative_to(config.folder)
11
+ colorize_section(">> #{relative_path}", config)
12
+ end
13
+
7
14
  def spec_file_error_line(spec_file, ex)
8
- str = colorize_highlight(spec_file.to_s)
9
- str += "\n " + colorize_error("X #{ex.message}")
15
+ str = ""
16
+ str += colorize_error(INDENT + "X #{ex.message}", config)
10
17
  if ex.root_cause && ex.root_cause != ex
11
- str += "\n " + colorize_error("#{ex.root_cause.message}")
18
+ str += "\n"
19
+ str += INDENT + colorize_error("#{ex.root_cause.message}", config)
12
20
  end
13
21
  str
14
22
  end
15
23
 
16
24
  def service_line(service, test_case)
17
- str = service.to_s + ", " + test_case.to_s
18
- str = colorize_highlight(str)
25
+ str = "#{service}, #{test_case}"
26
+ str = colorize_highlight(str, config)
19
27
  end
20
28
 
21
29
  def check_success_line(check)
22
- " " + colorize_success("v") + " " + check.behavior
30
+ INDENT + colorize_success("v " + check.behavior, config)
23
31
  end
24
32
 
25
33
  def check_failure_line(check, ex)
26
- " " + colorize_error("F " + ex.message)
34
+ INDENT + colorize_error("F " + ex.message, config)
27
35
  end
28
36
 
29
37
  def check_error_line(check, ex)
30
- " " + colorize_error("E " + ex.message)
38
+ INDENT + colorize_error("E " + ex.message, config)
31
39
  end
32
40
  end
33
41
  include Helpers
34
42
 
35
43
  def spec_file_error(e)
44
+ io.puts spec_file_line(spec_file)
45
+ io.puts
36
46
  io.puts spec_file_error_line(spec_file, e)
37
47
  io.puts
48
+ io.flush
49
+ end
50
+
51
+ def before_service
52
+ io.puts spec_file_line(spec_file)
53
+ io.puts
54
+ io.flush
38
55
  end
39
56
 
40
57
  def before_test_case
41
58
  io.puts service_line(service, test_case)
59
+ io.flush
42
60
  end
43
61
 
44
62
  def check_success(check)
45
63
  io.puts check_success_line(check)
64
+ io.flush
46
65
  end
47
66
 
48
67
  def check_failure(check, ex)
49
68
  io.puts check_failure_line(check, ex)
69
+ io.flush
50
70
  end
51
71
 
52
72
  def check_error(check, ex)
53
73
  io.puts check_error_line(check, ex)
74
+ io.flush
54
75
  end
55
76
 
56
77
  def test_case_done
57
78
  io.puts
79
+ io.flush
58
80
  end
59
81
 
60
82
  def service_done
61
83
  io.puts
84
+ io.flush
62
85
  end
63
86
 
64
87
  end # class Documentation
@@ -5,18 +5,22 @@ module Webspicy
5
5
 
6
6
  def initialize(*args, &bl)
7
7
  super
8
- @error_count = 0
8
+ @errors = Hash.new{|h,k| 0 }
9
9
  end
10
+ attr_reader :errors
10
11
 
11
- def on_error(*args, &bl)
12
- @error_count += 1
12
+ [
13
+ :spec_file_error,
14
+ :check_error,
15
+ :check_failure
16
+ ].each do |meth|
17
+ define_method(meth) do |*args, &bl|
18
+ @errors[meth] += 1
19
+ end
13
20
  end
14
- alias :spec_file_error :on_error
15
- alias :check_failure :on_error
16
- alias :check_error :on_error
17
21
 
18
22
  def report
19
- @error_count
23
+ @errors.values.inject(0){|memo,x| memo+x }
20
24
  end
21
25
 
22
26
  end # class ErrorCount
@@ -33,6 +33,7 @@ module Webspicy
33
33
  io.puts e
34
34
  end
35
35
  io.puts
36
+ io.flush
36
37
  end
37
38
 
38
39
  def report_failed_results
@@ -52,6 +53,7 @@ module Webspicy
52
53
  io.puts
53
54
  end
54
55
  io.puts
56
+ io.flush
55
57
  end
56
58
 
57
59
  end # class Exceptions
@@ -4,16 +4,19 @@ module Webspicy
4
4
  class FileProgress < Reporter
5
5
 
6
6
  def spec_file_error(e)
7
- io.print colorize_error("X")
7
+ io.print colorize_error("X", config)
8
+ io.flush
8
9
  end
9
10
 
10
11
  def spec_file_done
11
- io.print colorize_success(".")
12
+ io.print colorize_success(".", config)
13
+ io.flush
12
14
  end
13
15
 
14
16
  def report
15
17
  io.puts
16
18
  io.puts
19
+ io.flush
17
20
  end
18
21
 
19
22
  end # class FileProgress
@@ -22,12 +22,13 @@ module Webspicy
22
22
  msg = "#{plural('spec file', spec_files_count)}, "\
23
23
  "#{plural('error', errors_count)}"
24
24
  if success?
25
- msg = colorize_success(msg)
25
+ msg = colorize_success(msg, config)
26
26
  else
27
- msg = colorize_error(msg)
27
+ msg = colorize_error(msg, config)
28
28
  end
29
29
  io.puts(msg)
30
30
  io.puts
31
+ io.flush
31
32
  end
32
33
 
33
34
  private
@@ -4,22 +4,24 @@ module Webspicy
4
4
  class Progress < Reporter
5
5
 
6
6
  def spec_file_error(e)
7
- io.print colorize_error("X")
7
+ io.print colorize_error("X", config)
8
8
  end
9
9
 
10
10
  def after_each_done
11
11
  if result.success?
12
- io.print colorize_success(".")
12
+ io.print colorize_success(".", config)
13
13
  elsif result.failure?
14
- io.print colorize_error("F")
14
+ io.print colorize_error("F", config)
15
15
  elsif result.error?
16
- io.print colorize_error("E")
16
+ io.print colorize_error("E", config)
17
17
  end
18
+ io.flush
18
19
  end
19
20
 
20
21
  def report
21
22
  io.puts
22
23
  io.puts
24
+ io.flush
23
25
  end
24
26
 
25
27
  end # class Progress
@@ -9,18 +9,21 @@ module Webspicy
9
9
  @examples_count = 0
10
10
  @counterexamples_count = 0
11
11
  @assertions_count = 0
12
+ #
13
+ @spec_file_errors_count = 0
12
14
  @errors_count = 0
13
15
  @failures_count = 0
14
16
  end
15
17
  attr_reader :spec_files_count, :examples_count, :counterexamples_count
16
- attr_reader :assertions_count, :errors_count, :failures_count
18
+ attr_reader :assertions_count
19
+ attr_reader :spec_file_errors_count, :errors_count, :failures_count
17
20
 
18
21
  def before_spec_file
19
22
  @spec_files_count += 1
20
23
  end
21
24
 
22
25
  def spec_file_error(e)
23
- @errors_count += 1
26
+ @spec_file_errors_count += 1
24
27
  end
25
28
 
26
29
  def after_each_done
@@ -42,18 +45,17 @@ module Webspicy
42
45
  "#{plural('error', errors_count)}, "\
43
46
  "#{plural('failure', failures_count)}"
44
47
  if success?
45
- msg = colorize_success(msg)
48
+ msg = colorize_success(msg, config)
46
49
  else
47
- msg = colorize_error(msg)
50
+ msg = colorize_error(msg, config)
48
51
  end
49
52
  io.puts(msg)
50
53
  io.puts
54
+ io.flush
51
55
  end
52
56
 
53
- private
54
-
55
57
  def success?
56
- @errors_count == 0 && @failures_count == 0
58
+ @spec_file_errors_count == 0 && @errors_count == 0 && @failures_count == 0
57
59
  end
58
60
 
59
61
  end # class Summary
@@ -5,26 +5,28 @@ module Webspicy
5
5
 
6
6
  def initialize(tester)
7
7
  @tester = tester
8
+ @scope = tester.scope
9
+ @client = tester.client
10
+ @specification = tester.specification
11
+ @service = tester.service
12
+ @test_case = tester.test_case
8
13
  @invocation = tester.invocation
9
14
  @assertions = []
10
15
  @failures = []
11
16
  @errors = []
12
- check!
17
+ if @invocation
18
+ check!
19
+ else
20
+ @errors << [InvocationSuceeded.new(self), tester.invocation_error]
21
+ end
13
22
  end
14
- attr_reader :tester, :invocation
23
+ attr_reader :tester, :scope, :client
24
+ attr_reader :specification, :service, :test_case, :invocation
15
25
  attr_reader :assertions, :failures, :errors
16
26
 
17
27
  def_delegators :@tester, *[
18
- :reporter
19
- ]
20
-
21
- def_delegators :@invocation, *[
22
28
  :config,
23
- :scope,
24
- :client,
25
- :specification,
26
- :service,
27
- :test_case
29
+ :reporter
28
30
  ]
29
31
 
30
32
  def self.from(tester)
@@ -94,13 +96,13 @@ module Webspicy
94
96
 
95
97
  def check_postconditions!
96
98
  service.postconditions.each do |c|
97
- check_one! Result::PostconditionMet.new(self, c)
99
+ check_one! Result::PostconditionMet.new(self, tester.bind_condition(c))
98
100
  end
99
101
  end
100
102
 
101
103
  def check_errconditions!
102
104
  service.errconditions.each do |c|
103
- check_one! Result::ErrconditionMet.new(self, c)
105
+ check_one! Result::ErrconditionMet.new(self, tester.bind_condition(c))
104
106
  end
105
107
  end
106
108
 
@@ -130,6 +132,7 @@ module Webspicy
130
132
  end # class Tester
131
133
  end # module Webspicy
132
134
  require_relative "result/check"
135
+ require_relative "result/invocation_succeeded"
133
136
  require_relative "result/response_status_met"
134
137
  require_relative "result/response_header_met"
135
138
  require_relative "result/output_schema_met"
@@ -18,9 +18,7 @@ module Webspicy
18
18
  end
19
19
 
20
20
  def call
21
- if err = post.check(invocation)
22
- _! err
23
- end
21
+ post.check!
24
22
  end
25
23
 
26
24
  end # class ErrconditionMet
@@ -12,6 +12,7 @@ module Webspicy
12
12
  end
13
13
 
14
14
  def call
15
+ return unless invocation.is_structured_output?
15
16
  output = invocation.loaded_body
16
17
  service.error_schema.dress(output)
17
18
  rescue Finitio::TypeError => ex
@@ -0,0 +1,13 @@
1
+ module Webspicy
2
+ class Tester
3
+ class Result
4
+ class InvocationSuceeded < Check
5
+
6
+ def initialize(result)
7
+ super(result)
8
+ end
9
+
10
+ end # class InvocationSuceeded
11
+ end # class Result
12
+ end # class Tester
13
+ end # module Webspicy
@@ -12,6 +12,7 @@ module Webspicy
12
12
  end
13
13
 
14
14
  def call
15
+ return unless invocation.is_structured_output?
15
16
  output = invocation.loaded_body
16
17
  service.output_schema.dress(output)
17
18
  rescue Finitio::TypeError => ex
@@ -18,9 +18,7 @@ module Webspicy
18
18
  end
19
19
 
20
20
  def call
21
- if err = post.check(invocation)
22
- _! err
23
- end
21
+ post.check!
24
22
  end
25
23
 
26
24
  end # class PostconditionMet
@@ -1,8 +1,8 @@
1
1
  module Webspicy
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 19
5
- TINY = 0
4
+ MINOR = 20
5
+ TINY = 4
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
@@ -36,11 +36,14 @@ module Webspicy
36
36
  response.body.to_s
37
37
  end
38
38
 
39
- def loaded_output
39
+ def is_structured_output?
40
40
  ct = response.content_type || test_case.expected_content_type
41
41
  ct = ct.mime_type if ct.respond_to?(:mime_type)
42
- case ct
43
- when %r{json}
42
+ ct =~ /json/
43
+ end
44
+
45
+ def loaded_output
46
+ if is_structured_output?
44
47
  raise "Body empty while expected" if raw_output.empty?
45
48
  @loaded_output ||= ::JSON.parse(response.body)
46
49
  else
@@ -50,6 +53,7 @@ module Webspicy
50
53
  alias :loaded_body :loaded_output
51
54
 
52
55
  def output
56
+ return loaded_output unless is_structured_output?
53
57
  schema = is_expected_success? ? service.output_schema : service.error_schema
54
58
  begin
55
59
  schema.dress(loaded_output)
@@ -0,0 +1,24 @@
1
+ ---
2
+ command:
3
+ webspicy {options} {args}
4
+
5
+ examples:
6
+
7
+ - description: |-
8
+ when called on a passing path
9
+ args:
10
+ - ./fixtures/passing/config.rb
11
+ assert:
12
+ exit_code:
13
+ 0
14
+ stdout: |-
15
+ GET /, when requested
16
+ v It has a 200 response status
17
+ v It has a `Content-Type: application/json` response header
18
+ v Its output meets the expected data schema
19
+ v Assert notEmpty
20
+ v Assert pathFD('', :hello => "World" )
21
+
22
+
23
+ 1 spec file, 1 example, 0 counterexample
24
+ 5 assertions, 0 error, 0 failure