teaspoon 1.1.2 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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 +25 -11
- 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/_boot.html.erb +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 -16
- 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 +10 -17
- data/lib/teaspoon/driver/capybara_webkit.rb +0 -40
@@ -1,4 +1,4 @@
|
|
1
|
-
<%= javascript_include_tag *@suite.spec_assets, debug: @suite.config.expand_assets %>
|
1
|
+
<%= javascript_include_tag *@suite.spec_assets, debug: @suite.config.expand_assets, allow_non_precompiled: true %>
|
2
2
|
<script type="text/javascript">
|
3
3
|
Teaspoon.onWindowLoad(Teaspoon.execute);
|
4
4
|
</script>
|
@@ -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
|