webspicy 0.20.1 → 0.20.6

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/fakesmtp/email.rb +13 -0
  21. data/lib/webspicy/tester/reporter.rb +5 -0
  22. data/lib/webspicy/tester/reporter/documentation.rb +30 -8
  23. data/lib/webspicy/tester/reporter/error_count.rb +11 -7
  24. data/lib/webspicy/tester/reporter/file_progress.rb +2 -2
  25. data/lib/webspicy/tester/reporter/file_summary.rb +2 -2
  26. data/lib/webspicy/tester/reporter/progress.rb +4 -4
  27. data/lib/webspicy/tester/reporter/summary.rb +8 -7
  28. data/lib/webspicy/tester/result.rb +2 -2
  29. data/lib/webspicy/tester/result/errcondition_met.rb +1 -3
  30. data/lib/webspicy/tester/result/postcondition_met.rb +1 -3
  31. data/lib/webspicy/version.rb +1 -1
  32. data/lib/webspicy/web.rb +46 -0
  33. data/lib/webspicy/{formaldoc.fio → web/formaldoc.fio} +5 -13
  34. data/lib/webspicy/web/invocation.rb +1 -0
  35. data/lib/webspicy/web/specification.rb +68 -0
  36. data/lib/webspicy/web/specification/file_upload.rb +39 -0
  37. data/lib/webspicy/web/specification/service.rb +13 -0
  38. data/lib/webspicy/web/specification/test_case.rb +58 -0
  39. data/spec/unit/configuration/scope/test_expand_example.rb +11 -5
  40. data/spec/unit/specification/pre/test_global_request_headers.rb +3 -3
  41. data/spec/unit/specification/service/test_dress_params.rb +2 -2
  42. data/spec/unit/test_configuration.rb +1 -0
  43. data/spec/unit/tester/fakesmtp/test_email.rb +93 -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 +28 -19
  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
@@ -4,9 +4,9 @@ module Webspicy
4
4
  class MissingConditionImpl
5
5
  include Post
6
6
 
7
- def check
7
+ def check!
8
8
  msg = matching_description.gsub(/\(x\)/, "<!>")
9
- raise "#{msg} (not instrumented)"
9
+ fail!("#{msg} (not instrumented)")
10
10
  end
11
11
 
12
12
  end # class MissingConditionImpl
@@ -4,9 +4,9 @@ module Webspicy
4
4
  class UnexpectedConditionImpl
5
5
  include Post
6
6
 
7
- def check
7
+ def check!
8
8
  msg = matching_description.gsub(/\( \)/, "<x>")
9
- raise "#{msg} (is instrumented)"
9
+ fail!("#{msg} (is instrumented)")
10
10
  end
11
11
 
12
12
  end # class UnexpectedConditionImpl
@@ -10,6 +10,9 @@ module Webspicy
10
10
  end
11
11
  attr_accessor :specification
12
12
 
13
+ # Deprecated
14
+ alias :resource :specification
15
+
13
16
  def self.info(raw)
14
17
  new(raw)
15
18
  end
@@ -18,10 +21,6 @@ module Webspicy
18
21
  specification.config
19
22
  end
20
23
 
21
- def method
22
- @raw[:method]
23
- end
24
-
25
24
  def description
26
25
  @raw[:description]
27
26
  end
@@ -65,7 +64,7 @@ module Webspicy
65
64
  def generated_counterexamples
66
65
  preconditions.map{|pre|
67
66
  pre.counterexamples(self).map{|tc|
68
- tc = Webspicy.test_case(tc, Webspicy.current_scope)
67
+ tc = config.factory.test_case(tc, Webspicy.current_scope)
69
68
  tc.bind(self, true)
70
69
  }
71
70
  }.flatten
@@ -28,6 +28,9 @@ module Webspicy
28
28
  service.specification
29
29
  end
30
30
 
31
+ # Deprecated
32
+ alias :resource :specification
33
+
31
34
  def self.info(raw)
32
35
  new(raw)
33
36
  end
@@ -40,10 +43,6 @@ module Webspicy
40
43
  @raw[:seeds]
41
44
  end
42
45
 
43
- def headers
44
- @raw[:headers] ||= {}
45
- end
46
-
47
46
  def metadata
48
47
  @raw[:metadata] ||= {}
49
48
  end
@@ -52,47 +51,10 @@ module Webspicy
52
51
  @raw[:tags] ||= []
53
52
  end
54
53
 
55
- def dress_params
56
- @raw.fetch(:dress_params){ true }
57
- end
58
- alias :dress_params? :dress_params
59
-
60
- def params
61
- @raw[:params] || {}
62
- end
63
-
64
- def body
65
- @raw[:body]
66
- end
67
-
68
- def file_upload
69
- @raw[:file_upload]
70
- end
71
-
72
- def located_file_upload
73
- file_upload ? file_upload.locate(specification) : nil
74
- end
75
-
76
54
  def expected
77
55
  @raw[:expected] || {}
78
56
  end
79
57
 
80
- def expected_content_type
81
- expected[:content_type]
82
- end
83
-
84
- def expected_status
85
- expected[:status]
86
- end
87
-
88
- def is_expected_status?(status)
89
- expected_status === status
90
- end
91
-
92
- def has_expected_status?
93
- not expected[:status].nil?
94
- end
95
-
96
58
  def expected_error
97
59
  expected[:error]
98
60
  end
@@ -101,14 +63,6 @@ module Webspicy
101
63
  !expected_error.nil?
102
64
  end
103
65
 
104
- def expected_headers
105
- expected[:headers] || {}
106
- end
107
-
108
- def has_expected_headers?
109
- !expected_headers.empty?
110
- end
111
-
112
66
  def assert
113
67
  @raw[:assert] || []
114
68
  end
@@ -3,11 +3,17 @@ module Webspicy
3
3
  module Colorize
4
4
 
5
5
  def colorize(str, kind, config = nil)
6
+ return str if config && !config.colorize
6
7
  color = (config || self.config).colors[kind]
7
- ColorizedString[str].colorize(color)
8
+ Paint[str, color]
8
9
  end
9
10
  module_function :colorize
10
11
 
12
+ def colorize_section(str, cfg = nil)
13
+ colorize(str, :section, cfg)
14
+ end
15
+ module_function :colorize_section
16
+
11
17
  def colorize_highlight(str, cfg = nil)
12
18
  colorize(str, :highlight, cfg)
13
19
  end
@@ -15,7 +15,7 @@ module Webspicy
15
15
  @test_case = nil
16
16
  @invocation = nil
17
17
  @invocation_error = nil
18
- @reporter = default_reporter
18
+ @reporter = @config.reporter
19
19
  end
20
20
  attr_reader :config, :scope, :hooks, :client
21
21
  attr_reader :specification, :spec_file
@@ -31,15 +31,6 @@ module Webspicy
31
31
  config.failfast
32
32
  end
33
33
 
34
- def default_reporter
35
- @reporter = Reporter::Composite.new
36
- #@reporter << Reporter::Progress.new
37
- @reporter << Reporter::Documentation.new
38
- @reporter << Reporter::Exceptions.new
39
- @reporter << Reporter::Summary.new
40
- @reporter << Reporter::ErrorCount.new
41
- end
42
-
43
34
  def call
44
35
  reporter.init(self)
45
36
  begin
@@ -50,6 +41,11 @@ module Webspicy
50
41
  reporter.find(Reporter::ErrorCount).report
51
42
  end
52
43
 
44
+ def call!
45
+ res = call
46
+ abort("KO") unless res == 0
47
+ end
48
+
53
49
  def find_and_call(method, url, mutation)
54
50
  unless tc = scope.find_test_case(method, url)
55
51
  raise Error, "No such service `#{method} #{url}`"
@@ -61,6 +57,11 @@ module Webspicy
61
57
  end
62
58
  end
63
59
 
60
+ def bind_condition(c)
61
+ c = Specification::Oldies::Bridge.new(c) unless c.respond_to?(:bind)
62
+ c.bind(self)
63
+ end
64
+
64
65
  protected
65
66
 
66
67
  def run_config
@@ -68,19 +69,15 @@ module Webspicy
68
69
  @scope = scope
69
70
  @hooks = Support::Hooks.for(scope.config)
70
71
  @client = scope.get_client
71
- reporter.before_all
72
- @hooks.fire_before_all(self)
73
- reporter.before_all_done
74
- reporter.before_scope
75
72
  run_scope
76
- reporter.scope_done
77
- reporter.after_all
78
- @hooks.fire_after_all(self)
79
- reporter.after_all_done
80
73
  end
81
74
  end
82
75
 
83
76
  def run_scope
77
+ reporter.before_all
78
+ hooks.fire_before_all(self)
79
+ reporter.before_all_done
80
+ reporter.before_scope
84
81
  scope.each_specification_file do |spec_file|
85
82
  @specification = load_specification(spec_file)
86
83
  if @specification
@@ -92,12 +89,16 @@ module Webspicy
92
89
  raise FailFast
93
90
  end
94
91
  end
92
+ reporter.scope_done
93
+ reporter.after_all
94
+ hooks.fire_after_all(self)
95
+ reporter.after_all_done
95
96
  end
96
97
 
97
98
  def load_specification(spec_file)
98
99
  @spec_file = spec_file
99
100
  reporter.before_spec_file
100
- Webspicy.specification(spec_file.load, spec_file, scope)
101
+ config.factory.specification(spec_file.load, spec_file, scope)
101
102
  rescue *PASSTHROUGH_EXCEPTIONS
102
103
  raise
103
104
  rescue Exception => e
@@ -176,7 +177,7 @@ module Webspicy
176
177
  end
177
178
 
178
179
  def instrument_one(condition)
179
- condition.bind(self).instrument
180
+ bind_condition(condition).instrument
180
181
  rescue ArgumentError
181
182
  raise "#{condition.class} implements old PRE/POST contract"
182
183
  end
@@ -40,7 +40,7 @@ module Webspicy
40
40
  actual_size(target, path) == expected
41
41
  end
42
42
 
43
- def actual_size(target, path)
43
+ def actual_size(target, path)
44
44
  target = extract_path(target, path)
45
45
  respond_to!(target, :size).size
46
46
  end
@@ -68,7 +68,7 @@ module Webspicy
68
68
  an_array(target).find { |t| t[:id] == id }
69
69
  end
70
70
 
71
- def idFD(element, expected)
71
+ def idFD(element, expected)
72
72
  expected.keys.all? do |k|
73
73
  value_equal(expected[k], element[k])
74
74
  end
@@ -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
@@ -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,41 +4,63 @@ 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
+ 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)
14
+ end
15
+
7
16
  def spec_file_error_line(spec_file, ex)
8
- str = colorize_highlight(spec_file.to_s)
9
- str += "\n " + colorize_error("X #{ex.message}")
17
+ str = ""
18
+ str += colorize_error(INDENT + "X #{ex.message}", config)
10
19
  if ex.root_cause && ex.root_cause != ex
11
- str += "\n " + colorize_error("#{ex.root_cause.message}")
20
+ str += "\n"
21
+ str += INDENT + colorize_error("#{ex.root_cause.message}", config)
12
22
  end
13
23
  str
14
24
  end
15
25
 
16
26
  def service_line(service, test_case)
17
- str = service.to_s + ", " + test_case.to_s
18
- str = colorize_highlight(str)
27
+ str = "#{service}, #{test_case}"
28
+ str = colorize_highlight(str, config)
19
29
  end
20
30
 
21
31
  def check_success_line(check)
22
- " " + colorize_success("v") + " " + check.behavior
32
+ INDENT + colorize_success("v " + check.behavior, config)
23
33
  end
24
34
 
25
35
  def check_failure_line(check, ex)
26
- " " + colorize_error("F " + ex.message)
36
+ INDENT + colorize_error("F " + ex.message, config)
27
37
  end
28
38
 
29
39
  def check_error_line(check, ex)
30
- " " + colorize_error("E " + ex.message)
40
+ INDENT + colorize_error("E " + ex.message, config)
31
41
  end
32
42
  end
33
43
  include Helpers
34
44
 
35
45
  def spec_file_error(e)
46
+ io.puts spec_file_line(spec_file)
47
+ io.puts
36
48
  io.puts spec_file_error_line(spec_file, e)
37
49
  io.puts
38
50
  io.flush
39
51
  end
40
52
 
53
+ def before_service
54
+ @spec_file_line_printed = false
55
+ end
56
+
41
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
42
64
  io.puts service_line(service, test_case)
43
65
  io.flush
44
66
  end
@@ -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
@@ -4,12 +4,12 @@ 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
8
  io.flush
9
9
  end
10
10
 
11
11
  def spec_file_done
12
- io.print colorize_success(".")
12
+ io.print colorize_success(".", config)
13
13
  io.flush
14
14
  end
15
15
 
@@ -22,9 +22,9 @@ 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
@@ -4,16 +4,16 @@ 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
18
  io.flush
19
19
  end