bauxite 0.6.5 → 0.6.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/README.md +6 -5
- data/doc/Bauxite/Action.html +6 -12
- data/doc/Bauxite/Application.html +32 -0
- data/doc/Bauxite/Context.html +95 -30
- data/doc/Bauxite/Loggers/CompositeLogger.html +21 -15
- data/doc/Bauxite/Loggers/FileLogger.html +45 -4
- data/doc/Bauxite/Loggers/HtmlLogger.html +23 -15
- data/doc/Bauxite/Loggers/XtermLogger.html +14 -4
- data/doc/README_md.html +13 -10
- data/doc/created.rid +10 -10
- data/doc/index.html +13 -10
- data/doc/js/search_index.js +1 -1
- data/doc/table_of_contents.html +62 -52
- data/lib/bauxite/actions/capture.rb +5 -13
- data/lib/bauxite/application.rb +62 -11
- data/lib/bauxite/core/context.rb +37 -2
- data/lib/bauxite/loggers/composite.rb +11 -7
- data/lib/bauxite/loggers/file.rb +11 -2
- data/lib/bauxite/loggers/html.rb +23 -11
- data/lib/bauxite/loggers/xterm.rb +8 -0
- data/lib/bauxite.rb +1 -1
- data/test/asserth.bxt +1 -1
- metadata +2 -2
data/lib/bauxite/application.rb
CHANGED
@@ -53,6 +53,10 @@ module Bauxite
|
|
53
53
|
# Number of seconds to wait before issuing a timeout error. This
|
54
54
|
# timeout applies only to Selectors.
|
55
55
|
#
|
56
|
+
# [-o, \--open_timeout SECONDS]
|
57
|
+
# Number of seconds to wait before issuing a timeout error. This
|
58
|
+
# timeout applies only to page loading times (i.e. Net::HTTP).
|
59
|
+
#
|
56
60
|
# [-d, \--debug]
|
57
61
|
# If an error occurs, break into the debug console. This mode is very
|
58
62
|
# useful to try different selector combinations and debug
|
@@ -84,6 +88,8 @@ module Bauxite
|
|
84
88
|
# To see a complete list of the available loggers execute:
|
85
89
|
# bauxite -h
|
86
90
|
#
|
91
|
+
# Note that multiple instances of this option can be specified.
|
92
|
+
#
|
87
93
|
# [-L, \--logger-option OPTION]
|
88
94
|
# A <tt>name=value</tt> pair of options that are directly forwarded to
|
89
95
|
# the logger. This option argument can appear multiple times in the
|
@@ -106,12 +112,34 @@ module Bauxite
|
|
106
112
|
# To see a complete list of the available selectors execute:
|
107
113
|
# bauxite -h
|
108
114
|
#
|
115
|
+
# [-c, \--capture]
|
116
|
+
# If the test fails, capture a screenshot in the +output+ directory.
|
117
|
+
# See the \--output option below.
|
118
|
+
#
|
119
|
+
# [\--csv-summary FILE]
|
120
|
+
# Output a single-line CSV summary ideal to feed into the Plot Jenkins
|
121
|
+
# plugin. If +FILE+ is not specified, defaults to +summary.csv+
|
122
|
+
#
|
123
|
+
# [\--output DIR]
|
124
|
+
# Output directory for generated artifacts. Defaults to the current
|
125
|
+
# working directory.
|
126
|
+
#
|
109
127
|
# [-u, \--url URL]
|
110
128
|
# This option is an alias of:
|
111
129
|
# -p remote -P url=URL
|
112
130
|
# If +URL+ is not present <tt>http://localhost:4444/wd/hub</tt> will be
|
113
131
|
# assumed.
|
114
132
|
#
|
133
|
+
# [\--jenkins DIR]
|
134
|
+
# Configures default options for Jenkins integration. This option is an
|
135
|
+
# alias of:
|
136
|
+
# -p remote -P url=http://localhost:4444/wd/hub -l echo -l html
|
137
|
+
# -L html_package=true -c --csv-summary
|
138
|
+
# --output DIR
|
139
|
+
# Note that any of the options above can be overridden by specifying the
|
140
|
+
# option after the <tt>--jenkins</tt> option. For example:
|
141
|
+
# --jenkins -u selenium.my-organization.com:4445
|
142
|
+
#
|
115
143
|
# [-e, \--extension DIR]
|
116
144
|
# Loads every Ruby file (*.rb) inside +DIR+ (and subdirectories). This
|
117
145
|
# option can be used to load custom Bauxite extensions (e.g. Actions,
|
@@ -147,7 +175,7 @@ module Bauxite
|
|
147
175
|
class Application
|
148
176
|
def self.start #:nodoc:
|
149
177
|
options = {
|
150
|
-
:logger =>
|
178
|
+
:logger => [],
|
151
179
|
:verbose => false,
|
152
180
|
:break => false,
|
153
181
|
:driver => 'firefox',
|
@@ -160,7 +188,9 @@ module Bauxite
|
|
160
188
|
:logger_opt => {},
|
161
189
|
:extensions => []
|
162
190
|
}
|
163
|
-
|
191
|
+
|
192
|
+
default_logger = (ENV['TERM'] == 'xterm') ? 'xterm' : 'terminal'
|
193
|
+
|
164
194
|
OptionParser.new do |opts|
|
165
195
|
opts.banner = "Usage: bauxite [options] [files...]"
|
166
196
|
|
@@ -173,13 +203,19 @@ module Bauxite
|
|
173
203
|
end
|
174
204
|
self
|
175
205
|
end
|
176
|
-
def opts.
|
206
|
+
def opts.hash(*args)
|
177
207
|
on(*args[1..-1]) do |v|
|
178
208
|
n,v = v.split('=', 2)
|
179
209
|
@o[args[0]][n.to_sym] = v || true
|
180
210
|
end
|
181
211
|
self
|
182
212
|
end
|
213
|
+
def opts.multi(*args)
|
214
|
+
on(*args[1..-1]) do |v|
|
215
|
+
@o[args[0]] << v
|
216
|
+
end
|
217
|
+
self
|
218
|
+
end
|
183
219
|
opts.o = options
|
184
220
|
|
185
221
|
opts.separator ""
|
@@ -191,23 +227,36 @@ module Bauxite
|
|
191
227
|
.single(:debug , "-d", "--debug", "Break to debug on error. "+
|
192
228
|
"Start the debug console if no input files given.")
|
193
229
|
.single(:driver , "-p", "--provider PROVIDER" , "Driver provider")
|
194
|
-
.
|
195
|
-
.
|
196
|
-
.
|
230
|
+
.hash( :driver_opt , "-P", "--provider-option OPTION", "Provider options (name=value)")
|
231
|
+
.multi( :logger , "-l", "--logger LOGGER" , "Logger type ('#{default_logger}')")
|
232
|
+
.hash( :logger_opt , "-L", "--logger-option OPTION" , "Logger options (name=value)")
|
197
233
|
.single(:reset , "-r", "--reset" , "Reset driver between tests")
|
198
234
|
.single(:wait , "-w", "--wait" , "Wait for ENTER before exiting")
|
199
235
|
.single(:selector , "-s", "--selector SELECTOR" , "Default selector ('#{options[:selector]}')")
|
200
236
|
.single(:capture , "-c", "--capture" , "If the test fails, capture a screenshot")
|
201
|
-
.single(:csv , "--csv-summary FILE" , "Output a single-line CSV summary")
|
202
237
|
.single(:output , "--output DIR" , "Output directory for generated artifacts")
|
203
|
-
|
238
|
+
.multi( :extensions , "-e", "--extension DIR" , "Load extensions from DIR")
|
239
|
+
|
240
|
+
opts.on("-u", "--url [URL]", "Configure the remote provider listening in the given url") do |v|
|
204
241
|
v = 'localhost:4444' unless v
|
205
242
|
v = 'http://'+v unless v.match /^https?:\/\//
|
206
243
|
v = v + '/wd/hub' unless v.end_with? '/wd/hub'
|
207
244
|
options[:driver] = 'remote'
|
208
245
|
options[:driver_opt][:url] = v
|
209
246
|
end
|
210
|
-
|
247
|
+
|
248
|
+
opts.on("--csv-summary [FILE]", "Output a single-line CSV summary") { |v| options[:csv] = v || 'summary.csv' }
|
249
|
+
|
250
|
+
opts.on("--jenkins DIR", "Configure default options for Jenkins integration") do |v|
|
251
|
+
options[:driver] = 'remote'
|
252
|
+
options[:driver_opt][:url] = 'http://localhost:4444/wd/hub'
|
253
|
+
options[:logger] = ['echo', 'html']
|
254
|
+
options[:output] = v
|
255
|
+
options[:logger_opt][:html_package] = true
|
256
|
+
options[:capture] = true
|
257
|
+
options[:csv] = 'summary.csv'
|
258
|
+
end
|
259
|
+
|
211
260
|
opts.on("--version", "Show version") do
|
212
261
|
puts "bauxite #{Bauxite::VERSION}"
|
213
262
|
exit
|
@@ -232,7 +281,9 @@ module Bauxite
|
|
232
281
|
|
233
282
|
opts.separator ""
|
234
283
|
end.parse!
|
235
|
-
|
284
|
+
|
285
|
+
options[:logger] << default_logger unless options[:logger].size > 0
|
286
|
+
|
236
287
|
ctx = nil
|
237
288
|
begin
|
238
289
|
ctx = Context.new(options)
|
@@ -273,7 +324,7 @@ module Bauxite
|
|
273
324
|
ok = ctx.tests.inject(0) { |s,t| s + (t[:status] == 'OK' ? 1 : 0) }
|
274
325
|
failed = total - ok
|
275
326
|
time = ctx.tests.inject(0) { |s,t| s + t[:time] }
|
276
|
-
File.open(csv_file, 'w') do |f|
|
327
|
+
File.open(ctx.output_path(csv_file), 'w') do |f|
|
277
328
|
f.write "Total,OK,Failed,Time\n#{total},#{ok},#{failed},#{time}\n"
|
278
329
|
end
|
279
330
|
end
|
data/lib/bauxite/core/context.rb
CHANGED
@@ -23,6 +23,7 @@
|
|
23
23
|
require 'selenium-webdriver'
|
24
24
|
require 'readline'
|
25
25
|
require 'csv'
|
26
|
+
require 'pathname'
|
26
27
|
|
27
28
|
# Load dependencies and extensions without leaking dir into the global scope
|
28
29
|
lambda do
|
@@ -177,7 +178,12 @@ module Bauxite
|
|
177
178
|
# # and clicks the "Search" button.
|
178
179
|
#
|
179
180
|
def start(actions = [])
|
180
|
-
|
181
|
+
begin
|
182
|
+
_load_driver
|
183
|
+
rescue StandardError => e
|
184
|
+
print_error(e)
|
185
|
+
raise
|
186
|
+
end
|
181
187
|
return unless actions.size > 0
|
182
188
|
begin
|
183
189
|
actions.each do |action|
|
@@ -420,7 +426,13 @@ module Bauxite
|
|
420
426
|
# Constructs a Logger instance using +name+ as a hint for the logger
|
421
427
|
# type.
|
422
428
|
#
|
423
|
-
def self.load_logger(
|
429
|
+
def self.load_logger(loggers, options)
|
430
|
+
if loggers.is_a? Array
|
431
|
+
return Loggers::CompositeLogger.new(options, loggers)
|
432
|
+
end
|
433
|
+
|
434
|
+
name = loggers
|
435
|
+
|
424
436
|
log_name = (name || 'null').downcase
|
425
437
|
|
426
438
|
class_name = "#{log_name.capitalize}Logger"
|
@@ -555,6 +567,29 @@ module Bauxite
|
|
555
567
|
end
|
556
568
|
end
|
557
569
|
|
570
|
+
# Returns the output path for +path+ accounting for the
|
571
|
+
# <tt>__OUTPUT__</tt> variable.
|
572
|
+
#
|
573
|
+
# For example:
|
574
|
+
# # assuming --output /mnt/disk
|
575
|
+
#
|
576
|
+
# ctx.output_path '/tmp/myfile.txt'
|
577
|
+
# # => returns '/tmp/myfile.txt'
|
578
|
+
#
|
579
|
+
# ctx.output_path 'myfile.txt'
|
580
|
+
# # => returns '/mnt/disk/myfile.txt'
|
581
|
+
#
|
582
|
+
def output_path(path)
|
583
|
+
unless Pathname.new(path).absolute?
|
584
|
+
output = @variables['__OUTPUT__']
|
585
|
+
if output
|
586
|
+
Dir.mkdir output unless Dir.exists? output
|
587
|
+
path = File.join(output, path)
|
588
|
+
end
|
589
|
+
end
|
590
|
+
path
|
591
|
+
end
|
592
|
+
|
558
593
|
# ======================================================================= #
|
559
594
|
# :section: Metadata
|
560
595
|
# ======================================================================= #
|
@@ -24,19 +24,23 @@
|
|
24
24
|
#
|
25
25
|
# This composite logger forwards logging calls to each of its children.
|
26
26
|
#
|
27
|
-
#
|
27
|
+
# Composite logger options include:
|
28
|
+
# [<tt>loggers</tt>] A comma-separated list of logger names.
|
28
29
|
#
|
29
30
|
class Bauxite::Loggers::CompositeLogger
|
30
31
|
|
31
32
|
# Constructs a new composite logger instance.
|
32
|
-
def initialize(options)
|
33
|
-
unless
|
34
|
-
|
35
|
-
"
|
36
|
-
|
33
|
+
def initialize(options, loggers = nil)
|
34
|
+
unless loggers
|
35
|
+
unless options[:loggers]
|
36
|
+
raise ArgumentError, "Missing required logger option 'loggers'. "+
|
37
|
+
"The value of this option is a comma-separated list of valid loggers. "+
|
38
|
+
"For example loggers=xterm,file."
|
39
|
+
end
|
40
|
+
loggers = options[:loggers].split(',')
|
37
41
|
end
|
38
42
|
|
39
|
-
@loggers =
|
43
|
+
@loggers = loggers.map do |l|
|
40
44
|
Bauxite::Context::load_logger(l, options)
|
41
45
|
end
|
42
46
|
end
|
data/lib/bauxite/loggers/file.rb
CHANGED
@@ -25,6 +25,10 @@
|
|
25
25
|
# This logger outputs the raw action text for every action executed to
|
26
26
|
# the file specified in the +file+ logger option.
|
27
27
|
#
|
28
|
+
# File logger options include:
|
29
|
+
# [<tt>file</tt>] Output file name.
|
30
|
+
#
|
31
|
+
#
|
28
32
|
class Bauxite::Loggers::FileLogger < Bauxite::Loggers::NullLogger
|
29
33
|
|
30
34
|
# Constructs a new echo logger instance.
|
@@ -34,12 +38,17 @@ class Bauxite::Loggers::FileLogger < Bauxite::Loggers::NullLogger
|
|
34
38
|
unless @file and @file != ''
|
35
39
|
raise ArgumentError, "FileLogger configuration error: Undefined 'file' option."
|
36
40
|
end
|
37
|
-
|
41
|
+
@lines = []
|
42
|
+
end
|
43
|
+
|
44
|
+
# Completes the log execution.
|
45
|
+
def finalize(ctx)
|
46
|
+
File.open(ctx.output_path(@file), 'w') { |f| f.write(@lines.join("\n")) }
|
38
47
|
end
|
39
48
|
|
40
49
|
# Echoes the raw action text.
|
41
50
|
def log_cmd(action)
|
42
|
-
|
51
|
+
@lines << action.text
|
43
52
|
yield
|
44
53
|
end
|
45
54
|
end
|
data/lib/bauxite/loggers/html.rb
CHANGED
@@ -20,12 +20,20 @@
|
|
20
20
|
# SOFTWARE.
|
21
21
|
#++
|
22
22
|
|
23
|
-
|
23
|
+
require 'base64'
|
24
|
+
|
25
|
+
# Html logger.
|
24
26
|
#
|
25
|
-
# This logger
|
27
|
+
# This logger creates an HTML report of the test execution, linking to the
|
28
|
+
# captures taken, if any.
|
26
29
|
#
|
27
|
-
#
|
28
|
-
#
|
30
|
+
# Html logger options include:
|
31
|
+
# [<tt>html</tt>] Name of the outpus HTML report file. If not present, defaults
|
32
|
+
# to "test.html".
|
33
|
+
# [<tt>html_package</tt>] If set, embed captures into the HTML report file
|
34
|
+
# using the data URI scheme (base64 encoded). The
|
35
|
+
# captures embedded into the report are deleted from
|
36
|
+
# the filesystem.
|
29
37
|
#
|
30
38
|
class Bauxite::Loggers::HtmlLogger < Bauxite::Loggers::NullLogger
|
31
39
|
|
@@ -35,6 +43,7 @@ class Bauxite::Loggers::HtmlLogger < Bauxite::Loggers::NullLogger
|
|
35
43
|
super(options)
|
36
44
|
@data = []
|
37
45
|
@file = options[:html] || 'test.html'
|
46
|
+
@imgs = []
|
38
47
|
end
|
39
48
|
|
40
49
|
# Logs the specified string.
|
@@ -158,12 +167,9 @@ class Bauxite::Loggers::HtmlLogger < Bauxite::Loggers::NullLogger
|
|
158
167
|
html << "
|
159
168
|
</body>
|
160
169
|
</html>"
|
161
|
-
file = @file
|
162
|
-
if output != ''
|
163
|
-
file = File.join(output, file)
|
164
|
-
Dir.mkdir output unless Dir.exists? output
|
165
|
-
end
|
170
|
+
file = ctx.output_path(@file)
|
166
171
|
File.open(file, 'w') { |f| f.write html }
|
172
|
+
File.delete(*@imgs) if @imgs.size > 0
|
167
173
|
end
|
168
174
|
|
169
175
|
private
|
@@ -171,7 +177,13 @@ private
|
|
171
177
|
"\n"+depth.times.inject('') { |s,i| s + "\t" } + s
|
172
178
|
end
|
173
179
|
def _img(output, path)
|
174
|
-
|
175
|
-
|
180
|
+
if @options[:html_package]
|
181
|
+
content = Base64.encode64(File.open(path, 'r') { |f| f.read })
|
182
|
+
@imgs << path unless @imgs.include? path
|
183
|
+
"<img src='data:image/png;base64,#{content}'/>"
|
184
|
+
else
|
185
|
+
path = path[output.size+1..-1] unless output == ''
|
186
|
+
"<img src='#{path}'/>"
|
187
|
+
end
|
176
188
|
end
|
177
189
|
end
|
@@ -27,6 +27,14 @@ require_relative 'terminal'
|
|
27
27
|
# This logger outputs colorized lines using xterm (VT100/2) escape
|
28
28
|
# sequences.
|
29
29
|
#
|
30
|
+
# XTerm logger options include:
|
31
|
+
# [<tt>nc</tt>, <tt>color</tt>] If set to 'no', prints text without using
|
32
|
+
# colors. Note that positional escape sequences
|
33
|
+
# will still be used to show progress. To disable
|
34
|
+
# escape sequences completely, consider using the
|
35
|
+
# Bauxite::Loggers::TerminalLogger logger
|
36
|
+
# instead.
|
37
|
+
#
|
30
38
|
class Bauxite::Loggers::XtermLogger < Bauxite::Loggers::TerminalLogger
|
31
39
|
|
32
40
|
protected
|
data/lib/bauxite.rb
CHANGED
data/test/asserth.bxt
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
open "https://www.ruby-lang.org"
|
2
|
-
asserth "content-type=html" "
|
2
|
+
asserth "content-type=html" "status=^\d+ .*$"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bauxite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Patricio Zavolinsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: selenium-webdriver
|