spectre-core 1.15.2 → 2.0.1
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/exe/spectre +271 -463
- data/lib/spectre/assertion.rb +118 -250
- data/lib/spectre/expectation.rb +89 -0
- data/lib/spectre/helpers.rb +56 -59
- data/lib/spectre/version.rb +3 -0
- data/lib/spectre.rb +1510 -334
- metadata +57 -32
- data/lib/spectre/async.rb +0 -31
- data/lib/spectre/bag.rb +0 -17
- data/lib/spectre/curl.rb +0 -398
- data/lib/spectre/diagnostic.rb +0 -39
- data/lib/spectre/environment.rb +0 -30
- data/lib/spectre/http/basic_auth.rb +0 -25
- data/lib/spectre/http/keystone.rb +0 -99
- data/lib/spectre/http.rb +0 -394
- data/lib/spectre/logging/console.rb +0 -156
- data/lib/spectre/logging/file.rb +0 -106
- data/lib/spectre/logging.rb +0 -183
- data/lib/spectre/mixin.rb +0 -61
- data/lib/spectre/reporter/console.rb +0 -104
- data/lib/spectre/reporter.rb +0 -17
- data/lib/spectre/resources.rb +0 -53
@@ -1,99 +0,0 @@
|
|
1
|
-
require_relative '../http'
|
2
|
-
|
3
|
-
module Spectre::Http
|
4
|
-
class SpectreHttpRequest
|
5
|
-
def keystone url, username, password, project, domain, cert=nil
|
6
|
-
@__req['keystone'] = {} unless @__req.key? 'keystone'
|
7
|
-
|
8
|
-
@__req['keystone']['url'] = url
|
9
|
-
@__req['keystone']['username'] = username
|
10
|
-
@__req['keystone']['password'] = password
|
11
|
-
@__req['keystone']['project'] = project
|
12
|
-
@__req['keystone']['domain'] = domain
|
13
|
-
@__req['keystone']['cert'] = cert
|
14
|
-
|
15
|
-
@__req['auth'] = 'keystone'
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
module Keystone
|
20
|
-
@@cache = {}
|
21
|
-
|
22
|
-
def self.on_req _http, net_req, req
|
23
|
-
return unless req.key? 'keystone' and req['auth'] == 'keystone'
|
24
|
-
|
25
|
-
keystone_cfg = req['keystone']
|
26
|
-
|
27
|
-
if @@cache.key? keystone_cfg
|
28
|
-
token = @@cache[keystone_cfg]
|
29
|
-
else
|
30
|
-
token, _ = authenticate(
|
31
|
-
keystone_cfg['url'],
|
32
|
-
keystone_cfg['username'],
|
33
|
-
keystone_cfg['password'],
|
34
|
-
keystone_cfg['project'],
|
35
|
-
keystone_cfg['domain'],
|
36
|
-
keystone_cfg['cert'],
|
37
|
-
)
|
38
|
-
|
39
|
-
@@cache[keystone_cfg] = token
|
40
|
-
end
|
41
|
-
|
42
|
-
net_req['X-Auth-Token'] = token
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.authenticate keystone_url, username, password, project, domain, cert
|
46
|
-
auth_data = {
|
47
|
-
auth: {
|
48
|
-
identity: {
|
49
|
-
methods: ['password'],
|
50
|
-
password: {
|
51
|
-
user: {
|
52
|
-
name: username,
|
53
|
-
password: password,
|
54
|
-
domain: {
|
55
|
-
name: domain,
|
56
|
-
},
|
57
|
-
},
|
58
|
-
},
|
59
|
-
},
|
60
|
-
scope: {
|
61
|
-
project: {
|
62
|
-
name: project,
|
63
|
-
domain: {
|
64
|
-
name: domain,
|
65
|
-
},
|
66
|
-
},
|
67
|
-
},
|
68
|
-
},
|
69
|
-
}
|
70
|
-
|
71
|
-
keystone_url = keystone_url + '/' unless keystone_url.end_with? '/'
|
72
|
-
|
73
|
-
base_uri = URI(keystone_url)
|
74
|
-
uri = URI.join(base_uri, 'auth/tokens?nocatalog=true')
|
75
|
-
|
76
|
-
http = Net::HTTP.new(base_uri.host, base_uri.port)
|
77
|
-
|
78
|
-
if cert
|
79
|
-
http.use_ssl = true
|
80
|
-
http.ca_file = cert
|
81
|
-
end
|
82
|
-
|
83
|
-
req = Net::HTTP::Post.new(uri)
|
84
|
-
req.body = JSON.pretty_generate(auth_data)
|
85
|
-
req.content_type = 'application/json'
|
86
|
-
|
87
|
-
res = http.request(req)
|
88
|
-
|
89
|
-
raise "error while authenticating: #{res.code} #{res.message}\n#{res.body}" if res.code != '201'
|
90
|
-
|
91
|
-
[
|
92
|
-
res['X-Subject-Token'],
|
93
|
-
JSON.parse(res.body),
|
94
|
-
]
|
95
|
-
end
|
96
|
-
|
97
|
-
Spectre::Http.register(self)
|
98
|
-
end
|
99
|
-
end
|
data/lib/spectre/http.rb
DELETED
@@ -1,394 +0,0 @@
|
|
1
|
-
require_relative '../spectre'
|
2
|
-
require_relative '../spectre/logging'
|
3
|
-
|
4
|
-
require 'net/http'
|
5
|
-
require 'openssl'
|
6
|
-
require 'json'
|
7
|
-
require 'securerandom'
|
8
|
-
require 'logger'
|
9
|
-
require 'ostruct'
|
10
|
-
|
11
|
-
module Spectre
|
12
|
-
module Http
|
13
|
-
DEFAULT_HTTP_CONFIG = {
|
14
|
-
'method' => 'GET',
|
15
|
-
'path' => '',
|
16
|
-
'host' => nil,
|
17
|
-
'port' => 80,
|
18
|
-
'scheme' => 'http',
|
19
|
-
'use_ssl' => false,
|
20
|
-
'cert' => nil,
|
21
|
-
'headers' => nil,
|
22
|
-
'query' => nil,
|
23
|
-
'content_type' => nil,
|
24
|
-
'timeout' => 180,
|
25
|
-
'retries' => 0,
|
26
|
-
}
|
27
|
-
|
28
|
-
@@modules = []
|
29
|
-
|
30
|
-
class HttpError < Exception
|
31
|
-
end
|
32
|
-
|
33
|
-
class SpectreHttpRequest < Spectre::DslClass
|
34
|
-
class Headers
|
35
|
-
CONTENT_TYPE = 'Content-Type'
|
36
|
-
UNIQUE_HEADERS = [CONTENT_TYPE].freeze
|
37
|
-
end
|
38
|
-
|
39
|
-
def initialize request
|
40
|
-
@__req = request
|
41
|
-
end
|
42
|
-
|
43
|
-
def method method_name
|
44
|
-
@__req['method'] = method_name.upcase
|
45
|
-
end
|
46
|
-
|
47
|
-
def url base_url
|
48
|
-
@__req['base_url'] = base_url
|
49
|
-
end
|
50
|
-
|
51
|
-
def path url_path
|
52
|
-
@__req['path'] = url_path
|
53
|
-
end
|
54
|
-
|
55
|
-
def timeout seconds
|
56
|
-
@__req['timeout'] = seconds
|
57
|
-
end
|
58
|
-
|
59
|
-
def retries count
|
60
|
-
@__req['retries'] = count
|
61
|
-
end
|
62
|
-
|
63
|
-
def header name, value
|
64
|
-
@__req['headers'] ||= []
|
65
|
-
@__req['headers'].append [name, value.to_s.strip]
|
66
|
-
end
|
67
|
-
|
68
|
-
def param name, value
|
69
|
-
@__req['query'] ||= []
|
70
|
-
@__req['query'].append [name, value.to_s.strip]
|
71
|
-
end
|
72
|
-
|
73
|
-
def content_type media_type
|
74
|
-
@__req['content_type'] = media_type
|
75
|
-
end
|
76
|
-
|
77
|
-
def json data
|
78
|
-
data = data.to_h if data.is_a? OpenStruct
|
79
|
-
body JSON.pretty_generate(data)
|
80
|
-
|
81
|
-
content_type('application/json') unless @__req['content_type']
|
82
|
-
end
|
83
|
-
|
84
|
-
def body body_content
|
85
|
-
@__req['body'] = body_content.to_s
|
86
|
-
end
|
87
|
-
|
88
|
-
def ensure_success!
|
89
|
-
@__req['ensure_success'] = true
|
90
|
-
end
|
91
|
-
|
92
|
-
def ensure_success?
|
93
|
-
@__req['ensure_success']
|
94
|
-
end
|
95
|
-
|
96
|
-
def authenticate method
|
97
|
-
@__req['auth'] = method
|
98
|
-
end
|
99
|
-
|
100
|
-
def no_auth!
|
101
|
-
@__req['auth'] = 'none'
|
102
|
-
end
|
103
|
-
|
104
|
-
def certificate path
|
105
|
-
@__req['cert'] = path
|
106
|
-
end
|
107
|
-
|
108
|
-
def use_ssl!
|
109
|
-
@__req['use_ssl'] = true
|
110
|
-
end
|
111
|
-
|
112
|
-
def no_log!
|
113
|
-
@__req['no_log'] = true
|
114
|
-
end
|
115
|
-
|
116
|
-
def to_s
|
117
|
-
@__req.to_s
|
118
|
-
end
|
119
|
-
|
120
|
-
alias_method :auth, :authenticate
|
121
|
-
alias_method :cert, :certificate
|
122
|
-
alias_method :media_type, :content_type
|
123
|
-
end
|
124
|
-
|
125
|
-
class SpectreHttpHeader
|
126
|
-
def initialize headers
|
127
|
-
@headers = headers || {}
|
128
|
-
end
|
129
|
-
|
130
|
-
def [] key
|
131
|
-
return nil unless @headers.key?(key.downcase)
|
132
|
-
|
133
|
-
@headers[key.downcase].first
|
134
|
-
end
|
135
|
-
|
136
|
-
def to_s
|
137
|
-
@headers.to_s
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
class SpectreHttpResponse
|
142
|
-
attr_reader :code, :message, :headers, :body
|
143
|
-
|
144
|
-
def initialize net_res
|
145
|
-
@code = net_res.code.to_i
|
146
|
-
@message = net_res.message
|
147
|
-
@body = net_res.body
|
148
|
-
@headers = SpectreHttpHeader.new(net_res.to_hash)
|
149
|
-
@json_data = nil
|
150
|
-
end
|
151
|
-
|
152
|
-
def json
|
153
|
-
if !@body.nil? and @json_data.nil?
|
154
|
-
begin
|
155
|
-
@json_data = JSON.parse(@body, object_class: OpenStruct)
|
156
|
-
rescue JSON::ParserError
|
157
|
-
raise HttpError.new("Body content is not a valid JSON:\n#{@body}")
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
@json_data
|
162
|
-
end
|
163
|
-
|
164
|
-
def success?
|
165
|
-
@code < 400
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
|
170
|
-
class << self
|
171
|
-
@@http_cfg = {}
|
172
|
-
@@response = nil
|
173
|
-
@@request = nil
|
174
|
-
@@modules = []
|
175
|
-
@@secure_keys = []
|
176
|
-
|
177
|
-
def https name, &block
|
178
|
-
http(name, secure: true, &block)
|
179
|
-
end
|
180
|
-
|
181
|
-
def http name, secure: false, &block
|
182
|
-
req = DEFAULT_HTTP_CONFIG.clone
|
183
|
-
|
184
|
-
if @@http_cfg.key? name
|
185
|
-
req.deep_merge! @@http_cfg[name].deep_clone
|
186
|
-
raise HttpError.new("No `base_url' set for HTTP client '#{name}'. Check your HTTP config in your environment.") unless req['base_url']
|
187
|
-
else
|
188
|
-
req['base_url'] = name
|
189
|
-
end
|
190
|
-
|
191
|
-
req['use_ssl'] = secure unless secure.nil?
|
192
|
-
|
193
|
-
SpectreHttpRequest.new(req)._evaluate(&block) if block_given?
|
194
|
-
|
195
|
-
invoke(req)
|
196
|
-
end
|
197
|
-
|
198
|
-
def request
|
199
|
-
raise 'No request has been invoked yet' unless @@request
|
200
|
-
|
201
|
-
@@request
|
202
|
-
end
|
203
|
-
|
204
|
-
def response
|
205
|
-
raise 'There is no response. No request has been invoked yet.' unless @@response
|
206
|
-
|
207
|
-
@@response
|
208
|
-
end
|
209
|
-
|
210
|
-
def register mod
|
211
|
-
raise 'Module must not be nil' unless mod
|
212
|
-
|
213
|
-
@@modules << mod
|
214
|
-
end
|
215
|
-
|
216
|
-
private
|
217
|
-
|
218
|
-
def try_format_json str, pretty: false
|
219
|
-
return str unless str or str.empty?
|
220
|
-
|
221
|
-
begin
|
222
|
-
json = JSON.parse(str)
|
223
|
-
json.obfuscate!(@@secure_keys) unless @@debug
|
224
|
-
|
225
|
-
if pretty
|
226
|
-
str = JSON.pretty_generate(json)
|
227
|
-
else
|
228
|
-
str = JSON.dump(json)
|
229
|
-
end
|
230
|
-
rescue
|
231
|
-
# do nothing
|
232
|
-
end
|
233
|
-
|
234
|
-
str
|
235
|
-
end
|
236
|
-
|
237
|
-
def secure? key
|
238
|
-
@@secure_keys.any? { |x| key.to_s.downcase.include? x.downcase }
|
239
|
-
end
|
240
|
-
|
241
|
-
def header_to_s headers
|
242
|
-
s = ''
|
243
|
-
headers.each_header.each do |header, value|
|
244
|
-
value = '*****' if secure?(header) and not @@debug
|
245
|
-
s += "#{header.to_s.ljust(30, '.')}: #{value.to_s}\n"
|
246
|
-
end
|
247
|
-
s
|
248
|
-
end
|
249
|
-
|
250
|
-
def invoke req
|
251
|
-
@@request = nil
|
252
|
-
|
253
|
-
# Build URI
|
254
|
-
|
255
|
-
scheme = req['use_ssl'] ? 'https' : 'http'
|
256
|
-
base_url = req['base_url']
|
257
|
-
|
258
|
-
unless base_url.match /http(?:s)?:\/\//
|
259
|
-
base_url = scheme + '://' + base_url
|
260
|
-
end
|
261
|
-
|
262
|
-
if req['path']
|
263
|
-
base_url = base_url + '/' unless base_url.end_with? '/'
|
264
|
-
base_url += req['path']
|
265
|
-
end
|
266
|
-
|
267
|
-
uri = URI(base_url)
|
268
|
-
|
269
|
-
raise HttpError.new("'#{uri}' is not a valid uri") unless uri.host
|
270
|
-
|
271
|
-
# Build query parameters
|
272
|
-
|
273
|
-
uri.query = URI.encode_www_form(req['query']) unless not req['query'] or req['query'].empty?
|
274
|
-
|
275
|
-
# Create HTTP client
|
276
|
-
|
277
|
-
net_http = Net::HTTP.new(uri.host, uri.port)
|
278
|
-
net_http.read_timeout = req['timeout']
|
279
|
-
net_http.max_retries = req['retries']
|
280
|
-
|
281
|
-
if uri.scheme == 'https'
|
282
|
-
net_http.use_ssl = true
|
283
|
-
|
284
|
-
if req['cert']
|
285
|
-
raise HttpError.new("Certificate '#{req['cert']}' does not exist") unless File.exist? req['cert']
|
286
|
-
|
287
|
-
net_http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
288
|
-
net_http.ca_file = req['cert']
|
289
|
-
else
|
290
|
-
net_http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
# Create HTTP Request
|
295
|
-
|
296
|
-
net_req = Net::HTTPGenericRequest.new(req['method'], true, true, uri)
|
297
|
-
net_req.body = req['body']
|
298
|
-
net_req.content_type = req['content_type'] if req['content_type'] and not req['content_type'].empty?
|
299
|
-
|
300
|
-
if req['headers']
|
301
|
-
req['headers'].each do |header|
|
302
|
-
net_req[header[0]] = header[1]
|
303
|
-
end
|
304
|
-
end
|
305
|
-
|
306
|
-
req_id = SecureRandom.uuid()[0..5]
|
307
|
-
|
308
|
-
# Run HTTP modules
|
309
|
-
|
310
|
-
@@modules.each do |mod|
|
311
|
-
mod.on_req(net_http, net_req, req) if mod.respond_to? :on_req
|
312
|
-
end
|
313
|
-
|
314
|
-
# Log request
|
315
|
-
|
316
|
-
req_log = "[>] #{req_id} #{req['method']} #{uri}\n"
|
317
|
-
req_log += header_to_s(net_req)
|
318
|
-
|
319
|
-
unless req['body'].nil? or req['body'].empty?
|
320
|
-
unless req['no_log']
|
321
|
-
req_log += try_format_json(req['body'], pretty: true)
|
322
|
-
else
|
323
|
-
req_log += '[...]'
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
|
-
@@logger.info(req_log)
|
328
|
-
|
329
|
-
# Request
|
330
|
-
|
331
|
-
start_time = Time.now
|
332
|
-
|
333
|
-
begin
|
334
|
-
net_res = net_http.request(net_req)
|
335
|
-
rescue SocketError => e
|
336
|
-
raise HttpError.new("The request '#{req['method']} #{uri}' failed. Please check if the given URL '#{uri}' is valid and available or a corresponding HTTP config in the environment file exists. See log for more details. Original.\nOriginal error was: #{e.message}")
|
337
|
-
rescue Net::ReadTimeout
|
338
|
-
raise HttpError.new("HTTP timeout of #{net_http.read_timeout}s exceeded")
|
339
|
-
end
|
340
|
-
|
341
|
-
end_time = Time.now
|
342
|
-
|
343
|
-
req['started_at'] = start_time
|
344
|
-
req['finished_at'] = end_time
|
345
|
-
|
346
|
-
# Run HTTP modules
|
347
|
-
|
348
|
-
@@modules.each do |mod|
|
349
|
-
mod.on_res(net_http, net_res, req) if mod.respond_to? :on_res
|
350
|
-
end
|
351
|
-
|
352
|
-
# Log response
|
353
|
-
|
354
|
-
res_log = "[<] #{req_id} #{net_res.code} #{net_res.message} (#{end_time - start_time}s)\n"
|
355
|
-
res_log += header_to_s(net_res)
|
356
|
-
|
357
|
-
unless net_res.body.nil? or net_res.body.empty?
|
358
|
-
unless req['no_log']
|
359
|
-
res_log += try_format_json(net_res.body, pretty: true)
|
360
|
-
else
|
361
|
-
res_log += '[...]'
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
@@logger.info(res_log)
|
366
|
-
|
367
|
-
fail "Response code of #{req_id} did not indicate success: #{net_res.code} #{net_res.message}" if req['ensure_success'] and net_res.code.to_i >= 400
|
368
|
-
|
369
|
-
# Set global request and response variables
|
370
|
-
|
371
|
-
@@request = OpenStruct.new(req)
|
372
|
-
@@request.freeze
|
373
|
-
|
374
|
-
@@response = SpectreHttpResponse.new(net_res)
|
375
|
-
end
|
376
|
-
end
|
377
|
-
|
378
|
-
Spectre.register do |config|
|
379
|
-
@@logger = Spectre::Logging::ModuleLogger.new(config, 'spectre/http')
|
380
|
-
@@secure_keys = config['secure_keys'] || []
|
381
|
-
@@debug = config['debug']
|
382
|
-
|
383
|
-
if config.key? 'http'
|
384
|
-
@@http_cfg = {}
|
385
|
-
|
386
|
-
config['http'].each do |name, cfg|
|
387
|
-
@@http_cfg[name] = cfg
|
388
|
-
end
|
389
|
-
end
|
390
|
-
end
|
391
|
-
|
392
|
-
Spectre.delegate :http, :https, :request, :response, to: self
|
393
|
-
end
|
394
|
-
end
|
@@ -1,156 +0,0 @@
|
|
1
|
-
require 'ectoplasm'
|
2
|
-
|
3
|
-
module Spectre
|
4
|
-
module Logging
|
5
|
-
class Console
|
6
|
-
def initialize config
|
7
|
-
@indent = 2
|
8
|
-
@width = 80
|
9
|
-
|
10
|
-
if config.key? 'log_format'
|
11
|
-
@config = config['log_format']['console'] || {}
|
12
|
-
@indent = @config['indent'] || @indent
|
13
|
-
@width = @config['width'] || @width
|
14
|
-
@fmt_end_context = @config['end_context']
|
15
|
-
@fmt_sep = @config['separator']
|
16
|
-
@fmt_start_group = @config['start_group']
|
17
|
-
@fmt_end_group = @config['end_group']
|
18
|
-
end
|
19
|
-
|
20
|
-
@process = nil
|
21
|
-
@level = 0
|
22
|
-
end
|
23
|
-
|
24
|
-
def start_subject subject
|
25
|
-
puts subject.desc.blue
|
26
|
-
end
|
27
|
-
|
28
|
-
def start_context context
|
29
|
-
return unless context.__desc
|
30
|
-
|
31
|
-
puts (' ' * indent) + context.__desc.magenta
|
32
|
-
@level += 1
|
33
|
-
end
|
34
|
-
|
35
|
-
def end_context context
|
36
|
-
return unless context.__desc
|
37
|
-
|
38
|
-
@level -= 1
|
39
|
-
puts (' ' * indent) + @fmt_end_context.gsub('<desc>', context.__desc).magenta if @fmt_end_context
|
40
|
-
end
|
41
|
-
|
42
|
-
def start_spec spec, data=nil
|
43
|
-
text = spec.desc
|
44
|
-
text += " with #{data}" if data
|
45
|
-
puts (' ' * indent) + text.cyan
|
46
|
-
|
47
|
-
@level += 1
|
48
|
-
end
|
49
|
-
|
50
|
-
def end_spec _spec, _data
|
51
|
-
@level -= 1
|
52
|
-
end
|
53
|
-
|
54
|
-
def log_separator desc
|
55
|
-
if desc
|
56
|
-
desc = @fmt_sep.gsub('<indent>', ' ' * indent).gsub('<desc>', desc) if @fmt_sep
|
57
|
-
puts desc.blue
|
58
|
-
else
|
59
|
-
puts
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def start_group desc
|
64
|
-
desc = @fmt_start_group.gsub('<desc>', desc) if @fmt_start_group
|
65
|
-
puts (' ' * indent) + desc.blue
|
66
|
-
@level += 1
|
67
|
-
end
|
68
|
-
|
69
|
-
def end_group desc
|
70
|
-
if desc and @fmt_start_group
|
71
|
-
desc = @fmt_start_group.gsub('<desc>', desc) if @fmt_start_group
|
72
|
-
puts (' ' * indent) + desc.blue
|
73
|
-
end
|
74
|
-
|
75
|
-
@level -= 1
|
76
|
-
end
|
77
|
-
|
78
|
-
def log_process desc
|
79
|
-
print_line(desc)
|
80
|
-
@process = desc
|
81
|
-
@level += 1
|
82
|
-
end
|
83
|
-
|
84
|
-
def log_status _desc, status, annotation=nil
|
85
|
-
status = status.green if status == Status::OK
|
86
|
-
status = status.blue if status == Status::INFO
|
87
|
-
status = status.grey if status == Status::DEBUG
|
88
|
-
status = status.red if status == Status::FAILED
|
89
|
-
status = status.red if status == Status::ERROR
|
90
|
-
status = status.grey if status == Status::SKIPPED
|
91
|
-
|
92
|
-
txt = status
|
93
|
-
txt += ' ' + annotation if annotation
|
94
|
-
|
95
|
-
@level -= 1
|
96
|
-
|
97
|
-
if @process
|
98
|
-
puts txt
|
99
|
-
else
|
100
|
-
print_line('', status)
|
101
|
-
end
|
102
|
-
|
103
|
-
@process = nil
|
104
|
-
end
|
105
|
-
|
106
|
-
def log_info message
|
107
|
-
print_line(message, Status::INFO.blue)
|
108
|
-
end
|
109
|
-
|
110
|
-
def log_debug message
|
111
|
-
print_line(message, Status::DEBUG.grey)
|
112
|
-
end
|
113
|
-
|
114
|
-
def log_error _spec, exception
|
115
|
-
txt = (Status::ERROR + ' - ' + exception.class.name).red
|
116
|
-
print_line('', txt)
|
117
|
-
end
|
118
|
-
|
119
|
-
def log_skipped _spec, message=nil
|
120
|
-
txt = Status::SKIPPED
|
121
|
-
|
122
|
-
unless message.nil?
|
123
|
-
txt += ' - ' + message
|
124
|
-
end
|
125
|
-
|
126
|
-
print_line('', txt.grey)
|
127
|
-
end
|
128
|
-
|
129
|
-
private
|
130
|
-
|
131
|
-
def indent
|
132
|
-
(@level+1) * @indent
|
133
|
-
end
|
134
|
-
|
135
|
-
def print_line text='', status=nil
|
136
|
-
puts if @process
|
137
|
-
|
138
|
-
ind = indent
|
139
|
-
line = (' ' * indent) + text
|
140
|
-
remaining = @width - text.length - ind
|
141
|
-
line += '.' * (@width - text.length - ind) if remaining > 0
|
142
|
-
|
143
|
-
print line
|
144
|
-
|
145
|
-
if status
|
146
|
-
puts status
|
147
|
-
@process = nil
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
Spectre.register do |config|
|
153
|
-
Spectre::Logging.add Console.new(config)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|