teaspoon 1.1.3 → 1.2.2
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 +5 -5
- data/CHANGELOG.md +47 -0
- data/MIT.LICENSE +2 -2
- data/README.md +56 -35
- data/app/assets/javascripts/teaspoon/hook.coffee +1 -1
- data/app/assets/javascripts/teaspoon/teaspoon.coffee +13 -1
- data/app/controllers/teaspoon/suite_controller.rb +18 -13
- data/app/views/teaspoon/suite/_boot.html.erb +1 -1
- data/app/views/teaspoon/suite/index.html.erb +1 -1
- data/lib/generators/teaspoon/install/install_generator.rb +34 -34
- data/lib/generators/teaspoon/install/templates/MISSING_FRAMEWORK +1 -1
- data/lib/generators/teaspoon/install/templates/POST_INSTALL +1 -1
- data/lib/generators/teaspoon/install/templates/env_comments.rb.tt +9 -7
- data/lib/tasks/teaspoon/info.rake +1 -1
- data/lib/teaspoon/command_line.rb +76 -76
- data/lib/teaspoon/configuration.rb +4 -4
- data/lib/teaspoon/console.rb +41 -40
- data/lib/teaspoon/coverage.rb +29 -25
- data/lib/teaspoon/deprecated.rb +1 -1
- data/lib/teaspoon/driver.rb +1 -1
- data/lib/teaspoon/driver/browserstack.rb +111 -0
- data/lib/teaspoon/driver/phantomjs.rb +25 -26
- data/lib/teaspoon/driver/phantomjs/runner.js +31 -3
- data/lib/teaspoon/driver/selenium.rb +13 -9
- data/lib/teaspoon/engine.rb +32 -27
- data/lib/teaspoon/environment.rb +28 -28
- data/lib/teaspoon/exceptions.rb +7 -7
- data/lib/teaspoon/exporter.rb +23 -23
- data/lib/teaspoon/formatter/base.rb +64 -46
- data/lib/teaspoon/formatter/clean.rb +2 -2
- data/lib/teaspoon/formatter/documentation.rb +40 -40
- data/lib/teaspoon/formatter/dot.rb +12 -12
- data/lib/teaspoon/formatter/json.rb +21 -21
- data/lib/teaspoon/formatter/junit.rb +52 -51
- data/lib/teaspoon/formatter/modules/report_module.rb +34 -32
- data/lib/teaspoon/formatter/pride.rb +21 -21
- data/lib/teaspoon/formatter/rspec_html.rb +31 -31
- data/lib/teaspoon/formatter/snowday.rb +6 -5
- data/lib/teaspoon/formatter/swayze_or_oprah.rb +91 -91
- data/lib/teaspoon/formatter/tap.rb +29 -29
- data/lib/teaspoon/formatter/tap_y.rb +57 -57
- data/lib/teaspoon/formatter/teamcity.rb +63 -63
- data/lib/teaspoon/framework/base.rb +1 -1
- data/lib/teaspoon/instrumentation.rb +18 -18
- data/lib/teaspoon/registry.rb +9 -9
- data/lib/teaspoon/registry/has_default.rb +2 -2
- data/lib/teaspoon/runner.rb +37 -37
- data/lib/teaspoon/server.rb +30 -29
- data/lib/teaspoon/suite.rb +68 -57
- data/lib/teaspoon/utility.rb +6 -0
- data/lib/teaspoon/version.rb +1 -1
- metadata +22 -15
- data/lib/teaspoon/driver/capybara_webkit.rb +0 -40
@@ -91,19 +91,21 @@ Teaspoon.configure do |config|
|
|
91
91
|
# Rake:
|
92
92
|
# teaspoon DRIVER=phantomjs SERVER_PORT=31337 FAIL_FAST=true FORMATTERS=junit suite=my_suite
|
93
93
|
|
94
|
-
# Specify which headless driver to use. Supports PhantomJS and
|
94
|
+
# Specify which headless driver to use. Supports PhantomJS, Selenium Webdriver and BrowserStack Webdriver.
|
95
95
|
#
|
96
96
|
# Available: <%= Teaspoon::Driver.available.keys.map{|f| ":#{f}"}.join(", ") %>
|
97
|
-
# PhantomJS: https://github.com/
|
98
|
-
# Selenium Webdriver: https://github.com/
|
99
|
-
#
|
97
|
+
# PhantomJS: https://github.com/jejacks0n/teaspoon/wiki/Using-PhantomJS
|
98
|
+
# Selenium Webdriver: https://github.com/jejacks0n/teaspoon/wiki/Using-Selenium-WebDriver
|
99
|
+
# BrowserStack Webdriver: https://github.com/jejacks0n/teaspoon/wiki/Using-BrowserStack-WebDriver
|
100
|
+
# Capybara Webkit: https://github.com/jejacks0n/teaspoon/wiki/Using-Capybara-Webkit
|
100
101
|
#config.driver = :<%= Teaspoon::Driver.default %>
|
101
102
|
|
102
103
|
# Specify additional options for the driver.
|
103
104
|
#
|
104
|
-
# PhantomJS: https://github.com/
|
105
|
-
# Selenium Webdriver: https://github.com/
|
106
|
-
#
|
105
|
+
# PhantomJS: https://github.com/jejacks0n/teaspoon/wiki/Using-PhantomJS
|
106
|
+
# Selenium Webdriver: https://github.com/jejacks0n/teaspoon/wiki/Using-Selenium-WebDriver
|
107
|
+
# BrowserStack Webdriver: https://github.com/jejacks0n/teaspoon/wiki/Using-BrowserStack-WebDriver
|
108
|
+
# Capybara Webkit: https://github.com/jejacks0n/teaspoon/wiki/Using-Capybara-Webkit
|
107
109
|
#config.driver_options = nil
|
108
110
|
|
109
111
|
# Specify the timeout for the driver. Specs are expected to complete within this time frame or the run will be
|
@@ -32,113 +32,113 @@ module Teaspoon
|
|
32
32
|
|
33
33
|
protected
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
def opts_for_general
|
36
|
+
opt :environment, "-r", "--require FILE",
|
37
|
+
"Require Teaspoon environment file."
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
# opt :custom_options_file,
|
40
|
+
# "-O", "--options PATH",
|
41
|
+
# "Specify the path to a custom options file."
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
opt :driver, "-d", "--driver DRIVER",
|
44
|
+
"Specify driver:",
|
45
|
+
*driver_details
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
47
|
+
opt :driver_options, "--driver-options OPTIONS",
|
48
|
+
"Specify driver-specific options to pass into the driver.",
|
49
|
+
" e.g. \"--ssl-protocol=any --ssl-certificates-path=/path/to/certs\".",
|
50
|
+
" Driver options are only supported with phantomjs."
|
51
51
|
|
52
|
-
|
53
|
-
|
52
|
+
opt :driver_timeout, "--driver-timeout SECONDS",
|
53
|
+
"Sets the timeout for the driver to wait before exiting."
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
opt :server, "--server SERVER",
|
56
|
+
"Sets server to use with Rack.",
|
57
|
+
" e.g. webrick, thin"
|
58
58
|
|
59
|
-
|
60
|
-
|
59
|
+
opt :server_host, "--server-host HOST",
|
60
|
+
"Sets the server to use a specific host."
|
61
61
|
|
62
|
-
|
63
|
-
|
62
|
+
opt :server_port, "--server-port PORT",
|
63
|
+
"Sets the server to use a specific port."
|
64
64
|
|
65
|
-
|
66
|
-
|
65
|
+
opt :server_timeout, "--server-timeout SECONDS",
|
66
|
+
"Sets the timeout that the server must start within."
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
|
68
|
+
opt :fail_fast, "-F", "--[no-]fail-fast",
|
69
|
+
"Abort after the first failing suite."
|
70
|
+
end
|
71
71
|
|
72
|
-
|
73
|
-
|
72
|
+
def opts_for_filtering
|
73
|
+
separator("Filtering")
|
74
74
|
|
75
|
-
|
76
|
-
|
75
|
+
opt :suite, "-s", "--suite SUITE",
|
76
|
+
"Focus to a specific suite."
|
77
77
|
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
opt :filter, "-g", "--filter FILTER",
|
79
|
+
"Filter tests matching a specific filter."
|
80
|
+
end
|
81
81
|
|
82
|
-
|
83
|
-
|
82
|
+
def opts_for_output
|
83
|
+
separator("Output")
|
84
84
|
|
85
|
-
|
86
|
-
|
85
|
+
opt :suppress_log, "-q", "--[no-]suppress-log",
|
86
|
+
"Suppress logs coming from console[log/debug/error]."
|
87
87
|
|
88
|
-
|
89
|
-
|
88
|
+
opt :color, "-c", "--[no-]color",
|
89
|
+
"Enable/Disable color output."
|
90
90
|
|
91
|
-
|
92
|
-
|
91
|
+
opt :export, "-e", "--export [OUTPUT_PATH]",
|
92
|
+
"Exports the test suite as the full HTML (requires wget)."
|
93
93
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
94
|
+
opt :formatters, "-f", "--format FORMATTERS",
|
95
|
+
"Specify formatters (comma separated)",
|
96
|
+
*formatter_details
|
97
|
+
end
|
98
98
|
|
99
|
-
|
100
|
-
|
99
|
+
def opts_for_coverage
|
100
|
+
separator("Coverage")
|
101
101
|
|
102
|
-
|
103
|
-
|
104
|
-
|
102
|
+
opt :use_coverage, "-C", "--coverage CONFIG_NAME",
|
103
|
+
"Generate coverage reports using a pre-defined coverage configuration."
|
104
|
+
end
|
105
105
|
|
106
|
-
|
107
|
-
|
106
|
+
def opts_for_utility
|
107
|
+
separator("Utility")
|
108
108
|
|
109
|
-
|
110
|
-
|
111
|
-
|
109
|
+
@parser.on "-v", "--version", "Display the version." do
|
110
|
+
Teaspoon.abort(Teaspoon::VERSION, 0)
|
111
|
+
end
|
112
112
|
|
113
|
-
|
114
|
-
|
113
|
+
@parser.on "-h", "--help", "You're looking at it." do
|
114
|
+
Teaspoon.abort(@parser, 0)
|
115
|
+
end
|
115
116
|
end
|
116
|
-
end
|
117
117
|
|
118
118
|
private
|
119
119
|
|
120
|
-
|
121
|
-
|
122
|
-
|
120
|
+
def separator(message)
|
121
|
+
@parser.separator("\n **** #{message} ****\n\n")
|
122
|
+
end
|
123
123
|
|
124
|
-
|
125
|
-
|
126
|
-
|
124
|
+
def opt(config, *args)
|
125
|
+
@parser.on(*args, proc { |value| @options[config] = value })
|
126
|
+
end
|
127
127
|
|
128
|
-
|
129
|
-
|
130
|
-
|
128
|
+
def require_console
|
129
|
+
require "teaspoon/console"
|
130
|
+
end
|
131
131
|
|
132
|
-
|
133
|
-
|
134
|
-
|
132
|
+
def formatter_details
|
133
|
+
Teaspoon::Formatter.available.map do |name, options|
|
134
|
+
" #{name}#{' (default)' if options[:default]} - #{options[:description]}"
|
135
|
+
end
|
135
136
|
end
|
136
|
-
end
|
137
137
|
|
138
|
-
|
139
|
-
|
140
|
-
|
138
|
+
def driver_details
|
139
|
+
Teaspoon::Driver.available.map do |name, options|
|
140
|
+
" #{name}#{' (default)' if options[:default]}"
|
141
|
+
end
|
141
142
|
end
|
142
|
-
end
|
143
143
|
end
|
144
144
|
end
|
@@ -21,7 +21,7 @@ module Teaspoon
|
|
21
21
|
@@asset_paths = ["spec/javascripts", "spec/javascripts/stylesheets",
|
22
22
|
"test/javascripts", "test/javascripts/stylesheets"]
|
23
23
|
@@fixture_paths = ["spec/javascripts/fixtures", "test/javascripts/fixtures"]
|
24
|
-
@@asset_manifest = ["teaspoon.css", "teaspoon-filterer.js", "
|
24
|
+
@@asset_manifest = ["teaspoon.css", "teaspoon-filterer.js", "support/*.js"]
|
25
25
|
|
26
26
|
# console runner specific
|
27
27
|
|
@@ -54,7 +54,7 @@ module Teaspoon
|
|
54
54
|
# suite configurations
|
55
55
|
|
56
56
|
cattr_accessor :suite_configs
|
57
|
-
@@suite_configs = { "default" => { block: proc {} } }
|
57
|
+
@@suite_configs = { "default" => { block: proc { } } }
|
58
58
|
|
59
59
|
def self.suite(name = :default, &block)
|
60
60
|
@@suite_configs[name.to_s] = { block: block, instance: Suite.new(name, &block) }
|
@@ -66,7 +66,7 @@ module Teaspoon
|
|
66
66
|
:hooks, :expand_assets, :js_extensions
|
67
67
|
|
68
68
|
def initialize(name = nil)
|
69
|
-
@matcher = "{spec/javascripts,app/assets}/**/*_spec.{js,js.coffee,coffee}"
|
69
|
+
@matcher = "{spec/javascripts,app/assets}/**/*_spec.{js,js.coffee,coffee,es6,js.es6}"
|
70
70
|
@helper = "spec_helper"
|
71
71
|
@javascripts = []
|
72
72
|
@stylesheets = ["teaspoon"]
|
@@ -104,7 +104,7 @@ module Teaspoon
|
|
104
104
|
# coverage configurations
|
105
105
|
|
106
106
|
cattr_accessor :coverage_configs
|
107
|
-
@@coverage_configs = { "default" => { block: proc {} } }
|
107
|
+
@@coverage_configs = { "default" => { block: proc { } } }
|
108
108
|
|
109
109
|
def self.coverage(name = :default, &block)
|
110
110
|
@@coverage_configs[name.to_s] = { block: block, instance: Coverage.new(&block) }
|
data/lib/teaspoon/console.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "teaspoon/environment"
|
2
|
+
require "teaspoon/utility"
|
2
3
|
|
3
4
|
module Teaspoon
|
4
5
|
class Console
|
@@ -66,54 +67,54 @@ module Teaspoon
|
|
66
67
|
|
67
68
|
protected
|
68
69
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
70
|
+
def resolve(files = [])
|
71
|
+
return if files.blank?
|
72
|
+
files.uniq.each do |path|
|
73
|
+
if result = Teaspoon::Suite.resolve_spec_for(path)
|
74
|
+
suite = @suites[result[:suite]] ||= []
|
75
|
+
suite << result[:path]
|
76
|
+
end
|
75
77
|
end
|
76
78
|
end
|
77
|
-
end
|
78
79
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
80
|
+
def start_server
|
81
|
+
server = Teaspoon::Server.new
|
82
|
+
log("Starting the Teaspoon server...") unless server.responsive?
|
83
|
+
server.start
|
84
|
+
server
|
85
|
+
end
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
87
|
+
def suites
|
88
|
+
return [options[:suite]] if options[:suite].present?
|
89
|
+
return @suites.keys if @suites.present?
|
90
|
+
Teaspoon.configuration.suite_configs.keys
|
91
|
+
end
|
91
92
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
93
|
+
def driver
|
94
|
+
return @driver if @driver
|
95
|
+
driver = Teaspoon::Driver.fetch(Teaspoon.configuration.driver)
|
96
|
+
@driver = driver.new(Teaspoon.configuration.driver_options)
|
97
|
+
end
|
97
98
|
|
98
|
-
|
99
|
-
|
100
|
-
|
99
|
+
def base_url_for(suite)
|
100
|
+
["#{@server.url}#{Teaspoon.configuration.mount_at}", suite].join("/")
|
101
|
+
end
|
101
102
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
103
|
+
def url_for(suite, console = true)
|
104
|
+
url = [base_url_for(suite), filter(suite)].compact.join("?")
|
105
|
+
url += "#{(url.include?('?') ? '&' : '?')}reporter=Console" if console
|
106
|
+
url
|
107
|
+
end
|
107
108
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
109
|
+
def filter(suite)
|
110
|
+
parts = []
|
111
|
+
parts << "grep=#{CGI.escape(options[:filter])}" if options[:filter].present?
|
112
|
+
(@suites[suite] || options[:files] || []).flatten.each { |file| parts << "file[]=#{CGI.escape(file)}" }
|
113
|
+
"#{parts.join('&')}" if parts.present?
|
114
|
+
end
|
114
115
|
|
115
|
-
|
116
|
-
|
117
|
-
|
116
|
+
def log(str)
|
117
|
+
STDOUT.print("#{str}\n") unless Teaspoon.configuration.suppress_log
|
118
|
+
end
|
118
119
|
end
|
119
120
|
end
|
data/lib/teaspoon/coverage.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "open3"
|
2
|
+
|
1
3
|
module Teaspoon
|
2
4
|
class Coverage
|
3
5
|
def self.configuration(name = Teaspoon.configuration.use_coverage)
|
@@ -18,7 +20,6 @@ module Teaspoon
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def generate_reports(&block)
|
21
|
-
|
22
23
|
input_path do |input|
|
23
24
|
results = []
|
24
25
|
@config.reports.each do |format|
|
@@ -33,8 +34,8 @@ module Teaspoon
|
|
33
34
|
args = threshold_args
|
34
35
|
return if args.blank?
|
35
36
|
input_path do |input|
|
36
|
-
result =
|
37
|
-
return if
|
37
|
+
result, st = Open3.capture2e(@executable, "check-coverage", *args, input.shellescape)
|
38
|
+
return if st.exitstatus.zero?
|
38
39
|
result = result.scan(/ERROR: .*$/).join("\n").gsub("ERROR: ", "")
|
39
40
|
block.call(result) unless result.blank?
|
40
41
|
end
|
@@ -42,31 +43,34 @@ module Teaspoon
|
|
42
43
|
|
43
44
|
private
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
def self.normalize_config_name(name)
|
47
|
+
return "default" if name == true
|
48
|
+
name.to_s
|
49
|
+
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
def input_path(&block)
|
52
|
+
Dir.mktmpdir do |temp_path|
|
53
|
+
input_path = File.join(temp_path, "coverage.json")
|
54
|
+
File.open(input_path, "w") { |f| f.write(@data.to_json) }
|
55
|
+
block.call(input_path)
|
56
|
+
end
|
55
57
|
end
|
56
|
-
end
|
57
58
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
59
|
+
def generate_report(input, format)
|
60
|
+
output_path = File.join(@config.output_path, @suite_name)
|
61
|
+
result, st =
|
62
|
+
Open3.capture2e(
|
63
|
+
@executable, "report", "--include", input.shellescape, "--dir", output_path, format
|
64
|
+
)
|
65
|
+
return result.gsub("Done", "").gsub("Using reporter [#{format}]", "").strip if st.exitstatus.zero?
|
66
|
+
raise Teaspoon::DependencyError.new("Unable to generate #{format} coverage report:\n#{result}")
|
67
|
+
end
|
64
68
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
69
|
+
def threshold_args
|
70
|
+
%w{statements functions branches lines}.map do |assert|
|
71
|
+
threshold = @config.send(:"#{assert}")
|
72
|
+
"--#{assert}=#{threshold}" if threshold
|
73
|
+
end.compact
|
74
|
+
end
|
71
75
|
end
|
72
76
|
end
|