webspicy 0.20.1 → 0.20.6
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.
- checksums.yaml +4 -4
- data/bin/sandr +14 -0
- data/bin/search +2 -0
- data/bin/webspicy +3 -4
- data/lib/finitio/webspicy/shared.fio +10 -0
- data/lib/webspicy.rb +22 -53
- data/lib/webspicy/configuration.rb +17 -0
- data/lib/webspicy/configuration/scope.rb +3 -2
- data/lib/webspicy/configuration/single_url.rb +35 -25
- data/lib/webspicy/configuration/single_yml_file.rb +7 -2
- data/lib/webspicy/specification.rb +0 -55
- data/lib/webspicy/specification/oldies/bridge.rb +4 -1
- data/lib/webspicy/specification/post/missing_condition_impl.rb +2 -2
- data/lib/webspicy/specification/post/unexpected_condition_impl.rb +2 -2
- data/lib/webspicy/specification/service.rb +4 -5
- data/lib/webspicy/specification/test_case.rb +3 -49
- data/lib/webspicy/support/colorize.rb +7 -1
- data/lib/webspicy/tester.rb +21 -20
- data/lib/webspicy/tester/assertions.rb +2 -2
- data/lib/webspicy/tester/fakesmtp/email.rb +13 -0
- data/lib/webspicy/tester/reporter.rb +5 -0
- data/lib/webspicy/tester/reporter/documentation.rb +30 -8
- data/lib/webspicy/tester/reporter/error_count.rb +11 -7
- data/lib/webspicy/tester/reporter/file_progress.rb +2 -2
- data/lib/webspicy/tester/reporter/file_summary.rb +2 -2
- data/lib/webspicy/tester/reporter/progress.rb +4 -4
- data/lib/webspicy/tester/reporter/summary.rb +8 -7
- data/lib/webspicy/tester/result.rb +2 -2
- data/lib/webspicy/tester/result/errcondition_met.rb +1 -3
- data/lib/webspicy/tester/result/postcondition_met.rb +1 -3
- data/lib/webspicy/version.rb +1 -1
- data/lib/webspicy/web.rb +46 -0
- data/lib/webspicy/{formaldoc.fio → web/formaldoc.fio} +5 -13
- data/lib/webspicy/web/invocation.rb +1 -0
- data/lib/webspicy/web/specification.rb +68 -0
- data/lib/webspicy/web/specification/file_upload.rb +39 -0
- data/lib/webspicy/web/specification/service.rb +13 -0
- data/lib/webspicy/web/specification/test_case.rb +58 -0
- data/spec/unit/configuration/scope/test_expand_example.rb +11 -5
- data/spec/unit/specification/pre/test_global_request_headers.rb +3 -3
- data/spec/unit/specification/service/test_dress_params.rb +2 -2
- data/spec/unit/test_configuration.rb +1 -0
- data/spec/unit/tester/fakesmtp/test_email.rb +93 -0
- data/spec/unit/web/specification/test_instantiate_url.rb +36 -0
- data/spec/unit/web/specification/test_url_placeholders.rb +23 -0
- data/tasks/test.rake +2 -1
- metadata +28 -19
- data/lib/webspicy/specification/file_upload.rb +0 -37
- data/spec/unit/specification/test_instantiate_url.rb +0 -34
- data/spec/unit/specification/test_url_placeholders.rb +0 -21
@@ -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
|
-
|
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 =
|
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
|
-
|
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
|
data/lib/webspicy/tester.rb
CHANGED
@@ -15,7 +15,7 @@ module Webspicy
|
|
15
15
|
@test_case = nil
|
16
16
|
@invocation = nil
|
17
17
|
@invocation_error = nil
|
18
|
-
@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
|
-
|
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
|
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
|
@@ -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 =
|
9
|
-
str +=
|
17
|
+
str = ""
|
18
|
+
str += colorize_error(INDENT + "X #{ex.message}", config)
|
10
19
|
if ex.root_cause && ex.root_cause != ex
|
11
|
-
str += "\n
|
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
|
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
|
-
|
32
|
+
INDENT + colorize_success("v " + check.behavior, config)
|
23
33
|
end
|
24
34
|
|
25
35
|
def check_failure_line(check, ex)
|
26
|
-
|
36
|
+
INDENT + colorize_error("F " + ex.message, config)
|
27
37
|
end
|
28
38
|
|
29
39
|
def check_error_line(check, ex)
|
30
|
-
|
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
|
-
@
|
8
|
+
@errors = Hash.new{|h,k| 0 }
|
9
9
|
end
|
10
|
+
attr_reader :errors
|
10
11
|
|
11
|
-
|
12
|
-
|
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
|
-
@
|
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
|