teaspoon 0.7.9 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +382 -260
- data/app/assets/javascripts/teaspoon-angular.js +108 -26241
- data/app/assets/javascripts/teaspoon-jasmine.js +103 -2642
- data/app/assets/javascripts/teaspoon-mocha.js +109 -5416
- data/app/assets/javascripts/teaspoon-qunit.js +107 -2255
- data/app/assets/javascripts/teaspoon-teaspoon.js +0 -1
- data/app/assets/javascripts/teaspoon/angular.coffee +3 -1
- data/app/assets/javascripts/teaspoon/base/hook.coffee +21 -0
- data/app/assets/javascripts/teaspoon/base/reporters/html.coffee +26 -14
- data/app/assets/javascripts/teaspoon/base/reporters/html/progress_view.coffee +1 -1
- data/app/assets/javascripts/teaspoon/base/reporters/html/template.coffee +3 -3
- data/app/assets/javascripts/teaspoon/base/teaspoon.coffee +10 -1
- data/app/assets/javascripts/teaspoon/jasmine.coffee +3 -1
- data/app/assets/javascripts/teaspoon/mocha.coffee +3 -1
- data/app/assets/javascripts/teaspoon/mocha/reporters/html.coffee +1 -1
- data/app/assets/javascripts/teaspoon/qunit.coffee +3 -1
- data/app/assets/javascripts/teaspoon/qunit/reporters/html.coffee +1 -1
- data/app/assets/javascripts/teaspoon/teaspoon.coffee +0 -1
- data/app/assets/stylesheets/teaspoon.css +12 -8
- data/app/controllers/teaspoon/suite_controller.rb +32 -0
- data/app/views/teaspoon/suite/_body.html.erb +0 -0
- data/app/views/teaspoon/suite/_boot.html.erb +4 -0
- data/app/views/teaspoon/suite/_boot_require_js.html.erb +19 -0
- data/app/views/teaspoon/{spec/suites.html.erb → suite/index.html.erb} +6 -7
- data/app/views/teaspoon/suite/show.html.erb +19 -0
- data/bin/teaspoon +1 -1
- data/config/routes.rb +14 -4
- data/lib/generators/teaspoon/install/POST_INSTALL +2 -2
- data/lib/generators/teaspoon/install/install_generator.rb +22 -11
- data/lib/generators/teaspoon/install/templates/_body.html.erb +0 -0
- data/lib/generators/teaspoon/install/templates/_boot.html.erb +4 -0
- data/lib/generators/teaspoon/install/templates/jasmine/env.rb +11 -0
- data/lib/generators/teaspoon/install/templates/jasmine/env_comments.rb +182 -0
- data/lib/generators/teaspoon/install/templates/jasmine/spec_helper.coffee +8 -6
- data/lib/generators/teaspoon/install/templates/jasmine/spec_helper.js +8 -7
- data/lib/generators/teaspoon/install/templates/mocha/env.rb +11 -0
- data/lib/generators/teaspoon/install/templates/mocha/env_comments.rb +182 -0
- data/lib/generators/teaspoon/install/templates/mocha/spec_helper.coffee +13 -13
- data/lib/generators/teaspoon/install/templates/mocha/spec_helper.js +13 -13
- data/lib/generators/teaspoon/install/templates/qunit/env.rb +11 -0
- data/lib/generators/teaspoon/install/templates/qunit/env_comments.rb +182 -0
- data/lib/generators/teaspoon/install/templates/qunit/test_helper.coffee +6 -5
- data/lib/generators/teaspoon/install/templates/qunit/test_helper.js +6 -5
- data/lib/tasks/teaspoon.rake +9 -2
- data/lib/teaspoon.rb +4 -6
- data/lib/teaspoon/command_line.rb +116 -134
- data/lib/teaspoon/configuration.rb +144 -66
- data/lib/teaspoon/console.rb +70 -37
- data/lib/teaspoon/coverage.rb +42 -15
- data/lib/teaspoon/deprecated.rb +65 -0
- data/lib/teaspoon/drivers/base.rb +10 -0
- data/lib/teaspoon/drivers/phantomjs/runner.js +9 -11
- data/lib/teaspoon/drivers/phantomjs_driver.rb +21 -21
- data/lib/teaspoon/drivers/selenium_driver.rb +32 -13
- data/lib/teaspoon/engine.rb +32 -12
- data/lib/teaspoon/environment.rb +16 -12
- data/lib/teaspoon/exceptions.rb +41 -5
- data/lib/teaspoon/exporter.rb +52 -0
- data/lib/teaspoon/formatters/base.rb +171 -0
- data/lib/teaspoon/formatters/clean_formatter.rb +2 -4
- data/lib/teaspoon/formatters/documentation_formatter.rb +60 -0
- data/lib/teaspoon/formatters/dot_formatter.rb +12 -90
- data/lib/teaspoon/formatters/json_formatter.rb +36 -0
- data/lib/teaspoon/formatters/junit_formatter.rb +51 -32
- data/lib/teaspoon/formatters/modules/report_module.rb +76 -0
- data/lib/teaspoon/formatters/pride_formatter.rb +23 -27
- data/lib/teaspoon/formatters/snowday_formatter.rb +7 -11
- data/lib/teaspoon/formatters/swayze_or_oprah_formatter.rb +88 -64
- data/lib/teaspoon/formatters/tap_formatter.rb +18 -27
- data/lib/teaspoon/formatters/tap_y_formatter.rb +35 -45
- data/lib/teaspoon/formatters/teamcity_formatter.rb +69 -31
- data/lib/teaspoon/instrumentation.rb +33 -33
- data/lib/teaspoon/result.rb +2 -1
- data/lib/teaspoon/runner.rb +40 -28
- data/lib/teaspoon/server.rb +23 -25
- data/lib/teaspoon/suite.rb +52 -72
- data/lib/teaspoon/utility.rb +3 -14
- data/lib/teaspoon/version.rb +1 -1
- data/spec/dummy/app/assets/javascripts/integration/integration_spec.coffee +3 -0
- data/spec/dummy/app/assets/javascripts/integration/spec_helper.coffee +2 -0
- data/spec/dummy/config/application.rb +3 -0
- data/spec/features/console_reporter_spec.rb +48 -18
- data/spec/features/hooks_spec.rb +23 -41
- data/spec/features/html_reporter_spec.rb +38 -21
- data/spec/features/install_generator_spec.rb +34 -20
- data/spec/features/instrumentation_spec.rb +3 -2
- data/spec/fixtures/coverage.json +243 -0
- data/spec/javascripts/fixtures/_body.html.erb +1 -0
- data/spec/javascripts/jasmine_helper.coffee +1 -1
- data/spec/javascripts/teaspoon/base/fixture_spec.coffee +4 -4
- data/spec/javascripts/teaspoon/base/reporters/html_spec.coffee +9 -10
- data/spec/javascripts/teaspoon/mocha/reporters/html_mspec.coffee +0 -6
- data/spec/javascripts/teaspoon/phantomjs/runner_spec.coffee +5 -6
- data/spec/javascripts/turbolinks_helper.coffee +1 -1
- data/spec/spec_helper.rb +3 -4
- data/spec/teaspoon/command_line_spec.rb +139 -23
- data/spec/teaspoon/configuration_spec.rb +164 -46
- data/spec/teaspoon/console_spec.rb +142 -47
- data/spec/teaspoon/coverage_spec.rb +98 -28
- data/spec/teaspoon/drivers/base_spec.rb +5 -0
- data/spec/teaspoon/drivers/phantomjs_driver_spec.rb +32 -14
- data/spec/teaspoon/drivers/selenium_driver_spec.rb +32 -24
- data/spec/teaspoon/engine_spec.rb +8 -5
- data/spec/teaspoon/environment_spec.rb +56 -33
- data/spec/teaspoon/exceptions_spec.rb +57 -0
- data/spec/teaspoon/exporter_spec.rb +96 -0
- data/spec/teaspoon/formatters/base_spec.rb +259 -0
- data/spec/teaspoon/formatters/clean_formatter_spec.rb +37 -0
- data/spec/teaspoon/formatters/documentation_formatter_spec.rb +127 -0
- data/spec/teaspoon/formatters/dot_formatter_spec.rb +52 -56
- data/spec/teaspoon/formatters/json_formatter_spec.rb +77 -0
- data/spec/teaspoon/formatters/junit_formatter_spec.rb +72 -35
- data/spec/teaspoon/formatters/pride_formatter_spec.rb +37 -0
- data/spec/teaspoon/formatters/snowday_formatter_spec.rb +35 -0
- data/spec/teaspoon/formatters/tap_formatter_spec.rb +29 -81
- data/spec/teaspoon/formatters/tap_y_formatter_spec.rb +31 -141
- data/spec/teaspoon/formatters/teamcity_formatter_spec.rb +99 -42
- data/spec/teaspoon/instrumentation_spec.rb +44 -44
- data/spec/teaspoon/result_spec.rb +37 -0
- data/spec/teaspoon/runner_spec.rb +70 -59
- data/spec/teaspoon/server_spec.rb +34 -52
- data/spec/teaspoon/suite_spec.rb +42 -188
- data/spec/teaspoon_env.rb +39 -28
- data/vendor/assets/javascripts/{angular-scenario-1.0.5.js → angular/1.0.5.js} +0 -0
- data/vendor/assets/javascripts/{angular-scenario-1.0.5.MIT-LICENSE → angular/MIT-LICENSE} +0 -0
- data/vendor/assets/javascripts/{jasmine-1.3.1.js → jasmine/1.3.1.js} +0 -0
- data/vendor/assets/javascripts/jasmine/2.0.0.js +2412 -0
- data/vendor/assets/javascripts/{jasmine-1.3.1.MIT.LICENSE → jasmine/MIT.LICENSE} +0 -0
- data/vendor/assets/javascripts/{mocha-1.10.0.js → mocha/1.10.0.js} +1 -0
- data/vendor/assets/javascripts/mocha/1.17.1.js +5813 -0
- data/vendor/assets/javascripts/{mocha-1.10.1.MIT.LICENSE → mocha/MIT.LICENSE} +0 -0
- data/vendor/assets/javascripts/{qunit-1.12.0.js → qunit/1.12.0.js} +1 -1
- data/vendor/assets/javascripts/qunit/1.14.0.js +2288 -0
- data/vendor/assets/javascripts/{qunit-1.12.0.MIT.LICENSE → qunit/MIT.LICENSE} +0 -0
- data/vendor/assets/javascripts/support/chai.js +827 -385
- data/vendor/assets/javascripts/support/jasmine-jquery-1.7.0.js +720 -0
- data/vendor/assets/javascripts/support/jasmine-jquery-2.0.0.js +812 -0
- data/vendor/assets/javascripts/support/sinon-chai.js +17 -0
- data/vendor/assets/javascripts/support/sinon.js +1138 -643
- metadata +57 -36
- data/app/controllers/teaspoon/spec_controller.rb +0 -38
- data/app/helpers/teaspoon/spec_helper.rb +0 -36
- data/app/views/teaspoon/spec/_require_js.html.erb +0 -21
- data/app/views/teaspoon/spec/_standard.html.erb +0 -4
- data/app/views/teaspoon/spec/runner.html.erb +0 -19
- data/lib/generators/teaspoon/install/templates/env.rb +0 -38
- data/lib/generators/teaspoon/install/templates/jasmine/initializer.rb +0 -64
- data/lib/generators/teaspoon/install/templates/mocha/initializer.rb +0 -64
- data/lib/generators/teaspoon/install/templates/qunit/initializer.rb +0 -64
- data/lib/teaspoon/check_coverage.rb +0 -33
- data/lib/teaspoon/drivers/base_driver.rb +0 -10
- data/lib/teaspoon/exception_handling.rb +0 -18
- data/lib/teaspoon/formatters/base_formatter.rb +0 -63
- data/spec/dummy/config/initializers/teaspoon.rb +0 -41
- data/spec/teaspoon/check_coverage_spec.rb +0 -50
- data/spec/teaspoon/formatters/base_formatter_spec.rb +0 -45
- data/vendor/assets/javascripts/support/chai.MIT.LICENSE +0 -22
- data/vendor/assets/javascripts/support/expect.MIT.LICENSE +0 -22
- data/vendor/assets/javascripts/support/jasmine-jquery.MIT.LICENSE +0 -20
- data/vendor/assets/javascripts/support/jasmine-jquery.js +0 -659
- data/vendor/assets/javascripts/support/sinon-chai.MIT-ISH.LICENSE +0 -13
- data/vendor/assets/javascripts/support/sinon.BSD.LICENSE +0 -27
@@ -0,0 +1,65 @@
|
|
1
|
+
module Teaspoon
|
2
|
+
|
3
|
+
def self.setup(&block)
|
4
|
+
Teaspoon.dep("Teaspoon.setup is deprecated, use Teaspoon.configure instead. The /initializer/teaspoon.rb file should be removed, and a new teaspoon_env.rb file should be created by running the install generator.")
|
5
|
+
configure(&block)
|
6
|
+
end
|
7
|
+
|
8
|
+
@dep_notified = {}
|
9
|
+
def self.dep(message, category = nil)
|
10
|
+
return if Teaspoon.configured
|
11
|
+
if category
|
12
|
+
return if @dep_notified[category]
|
13
|
+
@dep_notified[category] = true if category
|
14
|
+
end
|
15
|
+
puts "WARNING: Deprecated - #{message}"
|
16
|
+
end
|
17
|
+
|
18
|
+
class Configuration
|
19
|
+
|
20
|
+
def self.context=(*args)
|
21
|
+
Teaspoon.dep("the teaspoon context directive is no longer used, remove it from your configuration.")
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.fixture_path=(*args)
|
25
|
+
Teaspoon.dep("the teaspoon fixture_path directive has been changed to fixture_paths, which expects an array, please update your configuration.")
|
26
|
+
self.fixture_paths = args
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.driver_cli_options=(val)
|
30
|
+
Teaspoon.dep("the teaspoon driver_cli_options directive is no longer used, use driver_options instead.")
|
31
|
+
self.driver_options = val
|
32
|
+
end
|
33
|
+
|
34
|
+
@coverage_dep_message = <<-MESSAGE
|
35
|
+
teaspoon coverage directive has changed and is now more flexible, define coverage using a block instead:
|
36
|
+
config.coverage :CI do |coverage|
|
37
|
+
coverage.reports = ["html", "text-summary"]
|
38
|
+
coverage.output_path = "coverage"
|
39
|
+
coverage.statements = 50 # statement threshold required
|
40
|
+
coverage.functions = 50 # function threshold required
|
41
|
+
coverage.branches = 50 # branch threshold required
|
42
|
+
coverage.lines = nil # no line threshold
|
43
|
+
end
|
44
|
+
> run: teaspoon --coverage=CI --suite=default
|
45
|
+
> set: config.use_coverage = "CI"
|
46
|
+
MESSAGE
|
47
|
+
|
48
|
+
for method in %w{coverage coverage_reports coverage_output_dir statements_coverage_threshold functions_coverage_threshold branches_coverage_threshold lines_coverage_threshold}
|
49
|
+
define_singleton_method("#{method}=") do |val|
|
50
|
+
Teaspoon.dep(@coverage_dep_message, :coverage)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Suite
|
55
|
+
|
56
|
+
def js_config=(*args)
|
57
|
+
Teaspoon.dep("the teaspoon suite js_config directive is no longer used, use the install generator to install the boot partial and customize it instead.", :js_config)
|
58
|
+
end
|
59
|
+
|
60
|
+
def normalize_asset_path=(*args)
|
61
|
+
Teaspoon.dep("the teaspoon suite normalize_asset_path directive is no longer used, reopen Teaspoon::Suite and define a normalize_js_extension method instead.", :normalize_asset_path)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -26,15 +26,11 @@
|
|
26
26
|
};
|
27
27
|
|
28
28
|
Runner.prototype.loadPage = function() {
|
29
|
-
var method, name, _ref, _results;
|
30
29
|
this.page.open(this.url);
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
method = _ref[name];
|
35
|
-
_results.push(this.page[name] = method);
|
30
|
+
var callbacks = this.pageCallbacks();
|
31
|
+
for (var name in callbacks) {
|
32
|
+
this.page[name] = callbacks[name];
|
36
33
|
}
|
37
|
-
return _results;
|
38
34
|
};
|
39
35
|
|
40
36
|
Runner.prototype.waitForResults = function() {
|
@@ -46,17 +42,16 @@
|
|
46
42
|
Runner.prototype.fail = function(msg, errno) {
|
47
43
|
if (msg == null) msg = null;
|
48
44
|
if (errno == null) errno = 1;
|
49
|
-
if (msg) console.log("Error: " + msg);
|
50
45
|
|
51
46
|
console.log(JSON.stringify({
|
52
47
|
_teaspoon: true,
|
53
|
-
type: "exception"
|
48
|
+
type: "exception",
|
49
|
+
message: msg
|
54
50
|
}));
|
55
51
|
phantom.exit(errno);
|
56
52
|
};
|
57
53
|
|
58
54
|
Runner.prototype.finish = function() {
|
59
|
-
console.log(" ");
|
60
55
|
phantom.exit(0);
|
61
56
|
};
|
62
57
|
|
@@ -71,6 +66,9 @@
|
|
71
66
|
trace: trace
|
72
67
|
}));
|
73
68
|
_this.errored = true;
|
69
|
+
if (/^TeaspoonError: /.test(message || "")) {
|
70
|
+
_this.fail("Execution halted.");
|
71
|
+
}
|
74
72
|
},
|
75
73
|
|
76
74
|
onConsoleMessage: function(msg) {
|
@@ -78,7 +76,7 @@
|
|
78
76
|
if (_this.errorTimeout) clearTimeout(_this.errorTimeout);
|
79
77
|
if (_this.errored) {
|
80
78
|
_this.errorTimeout = setTimeout((function() {
|
81
|
-
return _this.fail(
|
79
|
+
return _this.fail("Javascript error has cause a timeout.");
|
82
80
|
}), 1000);
|
83
81
|
return _this.errored = false;
|
84
82
|
}
|
@@ -1,46 +1,46 @@
|
|
1
|
-
require "teaspoon/runner"
|
2
|
-
require 'teaspoon/utility'
|
3
|
-
|
4
1
|
begin
|
5
2
|
require "phantomjs"
|
6
3
|
rescue LoadError
|
4
|
+
# if we can't load phantomjs, assume the cli is installed and in the path
|
7
5
|
end
|
8
6
|
|
9
7
|
module Teaspoon
|
10
8
|
module Drivers
|
11
|
-
class PhantomjsDriver <
|
9
|
+
class PhantomjsDriver < Base
|
12
10
|
include Teaspoon::Utility
|
13
11
|
|
14
|
-
def
|
15
|
-
|
12
|
+
def initialize(options = nil)
|
13
|
+
options ||= []
|
14
|
+
case options
|
15
|
+
when Array then @options = options
|
16
|
+
when String then @options = options.split(" ")
|
17
|
+
when Hash then @options = options.map { |k, v| "--#{k}=#{v}" }
|
18
|
+
else raise Teaspoon::UnknownDriverOptions, "Unknown driver options -- supply a string, array or hash"
|
19
|
+
end
|
20
|
+
end
|
16
21
|
|
17
|
-
|
22
|
+
def run_specs(runner, url)
|
23
|
+
run(*driver_options(url)) do |line|
|
18
24
|
runner.process(line) if line && line.strip != ""
|
19
25
|
end
|
20
|
-
|
21
|
-
runner.failure_count
|
22
26
|
end
|
23
27
|
|
24
28
|
protected
|
25
29
|
|
26
30
|
def run(*args, &block)
|
27
|
-
IO.popen([executable, *args]) { |io|
|
28
|
-
io.each(&block)
|
29
|
-
}
|
31
|
+
IO.popen([executable, *args].join(' ')) { |io| io.each(&block) }
|
30
32
|
end
|
31
33
|
|
32
|
-
def
|
33
|
-
[
|
34
|
+
def driver_options(url)
|
35
|
+
[@options, script, url.shellescape, Teaspoon.configuration.driver_timeout].flatten.compact
|
34
36
|
end
|
35
37
|
|
36
38
|
def executable
|
37
|
-
executable
|
38
|
-
executable =
|
39
|
-
if executable.blank?
|
40
|
-
|
41
|
-
|
42
|
-
end
|
43
|
-
executable
|
39
|
+
return @executable if @executable
|
40
|
+
@executable = which("phantomjs")
|
41
|
+
@executable = Phantomjs.path if @executable.blank? && defined?(::Phantomjs)
|
42
|
+
return @executable unless @executable.blank?
|
43
|
+
raise Teaspoon::MissingDependency, "Could not find PhantomJS. Install phantomjs or try the phantomjs gem."
|
44
44
|
end
|
45
45
|
|
46
46
|
def script
|
@@ -1,32 +1,51 @@
|
|
1
|
-
|
2
|
-
require "
|
1
|
+
begin
|
2
|
+
require "selenium-webdriver"
|
3
|
+
rescue LoadError
|
4
|
+
STDOUT.print("Could not find Selenium Webdriver. Install the selenium-webdriver gem.\n")
|
5
|
+
exit(1)
|
6
|
+
end
|
3
7
|
|
4
8
|
module Teaspoon
|
5
9
|
module Drivers
|
6
|
-
class SeleniumDriver <
|
10
|
+
class SeleniumDriver < Base
|
11
|
+
|
12
|
+
def initialize(options = nil)
|
13
|
+
options ||= {}
|
14
|
+
case options
|
15
|
+
when Hash then @options = options
|
16
|
+
when String then @options = JSON.parse(options)
|
17
|
+
else raise Teaspoon::UnknownDriverOptions, "Unknown driver options -- supply a hash or json string"
|
18
|
+
end
|
7
19
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# supported by the binding that will take more thought and design to configure cleanly.
|
12
|
-
def run_specs(suite, url, driver_cli_options = nil)
|
13
|
-
runner = Teaspoon::Runner.new(suite)
|
20
|
+
rescue JSON::ParserError
|
21
|
+
raise Teaspoon::UnknownDriverOptions, "Malformed driver options -- supply a hash or json string"
|
22
|
+
end
|
14
23
|
|
15
|
-
|
24
|
+
def run_specs(runner, url)
|
25
|
+
driver = Selenium::WebDriver.for(driver_options[:client_driver])
|
16
26
|
driver.navigate.to(url)
|
17
27
|
|
18
|
-
Selenium::WebDriver::Wait.new(
|
28
|
+
Selenium::WebDriver::Wait.new(driver_options).until do
|
19
29
|
done = driver.execute_script("return window.Teaspoon && window.Teaspoon.finished")
|
20
30
|
driver.execute_script("return window.Teaspoon && window.Teaspoon.getMessages() || []").each do |line|
|
21
31
|
runner.process("#{line}\n")
|
22
32
|
end
|
23
33
|
done
|
24
34
|
end
|
25
|
-
|
26
|
-
runner.failure_count
|
27
35
|
ensure
|
28
36
|
driver.quit if driver
|
29
37
|
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def driver_options
|
42
|
+
@driver_options ||= HashWithIndifferentAccess.new({
|
43
|
+
client_driver: :firefox,
|
44
|
+
timeout: Teaspoon.configuration.driver_timeout.to_i,
|
45
|
+
interval: 0.01,
|
46
|
+
message: "Timed out"
|
47
|
+
}).merge(@options)
|
48
|
+
end
|
30
49
|
end
|
31
50
|
end
|
32
51
|
end
|
data/lib/teaspoon/engine.rb
CHANGED
@@ -1,30 +1,50 @@
|
|
1
|
-
require
|
1
|
+
require "teaspoon/environment"
|
2
|
+
require "teaspoon/suite"
|
3
|
+
require "teaspoon/instrumentation"
|
2
4
|
|
3
5
|
module Teaspoon
|
4
6
|
class Engine < ::Rails::Engine
|
5
7
|
|
6
8
|
isolate_namespace Teaspoon
|
7
9
|
|
8
|
-
initializer :assets, :
|
9
|
-
|
10
|
-
|
10
|
+
initializer :assets, group: :all do |app|
|
11
|
+
begin
|
12
|
+
Teaspoon::Environment.require_environment
|
13
|
+
rescue Teaspoon::EnvironmentNotFound
|
14
|
+
# it's ok for this to fail sometimes, like before the initializer is run etc
|
15
|
+
end
|
16
|
+
|
17
|
+
Teaspoon::Engine.default_root_path(app.root) # default the root if it's not set
|
18
|
+
Teaspoon::Engine.append_asset_paths(app.config.assets) # append the asset paths from the configuration
|
19
|
+
end
|
20
|
+
|
21
|
+
config.after_initialize do |app|
|
22
|
+
Teaspoon::Engine.inject_instrumentation # inject our sprockets hack for instrumenting javascripts
|
23
|
+
Teaspoon::Engine.prepend_routes(app) # prepend routes so a catchall doesn't get in the way
|
24
|
+
end
|
11
25
|
|
12
|
-
|
13
|
-
Teaspoon.configuration.context ||= app.config.relative_url_root
|
26
|
+
private
|
14
27
|
|
15
|
-
|
28
|
+
def self.default_root_path(root)
|
29
|
+
Teaspoon.configuration.root ||= root
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.append_asset_paths(assets)
|
16
33
|
Teaspoon.configuration.asset_paths.each do |path|
|
17
|
-
|
34
|
+
assets.paths << Teaspoon.configuration.root.join(path).to_s
|
18
35
|
end
|
19
36
|
end
|
20
37
|
|
21
|
-
|
22
|
-
# inject our sprockets hack for instrumenting javascripts
|
38
|
+
def self.inject_instrumentation
|
23
39
|
Sprockets::Environment.send(:include, Teaspoon::SprocketsInstrumentation)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.prepend_routes(app)
|
43
|
+
return if Teaspoon::Engine.routes.recognize_path('/') rescue nil
|
44
|
+
require Teaspoon::Engine.root.join("app/controllers/teaspoon/suite_controller")
|
24
45
|
|
25
|
-
# prepend routes so a catchall doesn't get in the way
|
26
46
|
app.routes.prepend do
|
27
|
-
mount Teaspoon::Engine => Teaspoon.configuration.mount_at
|
47
|
+
mount Teaspoon::Engine => Teaspoon.configuration.mount_at, as: "teaspoon"
|
28
48
|
end
|
29
49
|
end
|
30
50
|
end
|
data/lib/teaspoon/environment.rb
CHANGED
@@ -8,41 +8,45 @@ module Teaspoon
|
|
8
8
|
raise "Rails environment not found." unless rails_loaded?
|
9
9
|
|
10
10
|
require "teaspoon"
|
11
|
-
require "teaspoon/suite"
|
12
11
|
require "teaspoon/server"
|
13
|
-
require "teaspoon/
|
12
|
+
require "teaspoon/runner"
|
13
|
+
require "teaspoon/coverage"
|
14
|
+
require "teaspoon/exporter"
|
14
15
|
|
15
|
-
|
16
|
+
Teaspoon.configuration.override_from_options(options)
|
17
|
+
Teaspoon::ExceptionHandling.add_rails_handling
|
16
18
|
end
|
17
19
|
|
18
20
|
def self.require_environment(override = nil)
|
19
|
-
|
21
|
+
override ||= ENV["TEASPOON_ENV"]
|
22
|
+
if override
|
23
|
+
override = File.expand_path(override, Dir.pwd)
|
24
|
+
ENV["TEASPOON_ENV"] = override
|
25
|
+
return require_env(override)
|
26
|
+
end
|
20
27
|
|
21
28
|
standard_environments.each do |filename|
|
22
29
|
file = File.expand_path(filename, Dir.pwd)
|
23
30
|
return require_env(file) if File.exists?(file)
|
31
|
+
#file = File.expand_path(filename, File.join(Dir.pwd, '../..'))
|
32
|
+
#return require_env(file) if File.exists?(file)
|
24
33
|
end
|
25
34
|
|
26
|
-
raise Teaspoon::EnvironmentNotFound
|
35
|
+
raise Teaspoon::EnvironmentNotFound, "Unable to load Teaspoon environment in {#{standard_environments.join(', ')}}"
|
27
36
|
end
|
28
37
|
|
29
38
|
def self.standard_environments
|
30
39
|
["spec/teaspoon_env.rb", "test/teaspoon_env.rb", "teaspoon_env.rb"]
|
31
40
|
end
|
32
41
|
|
33
|
-
|
34
|
-
options.each do |key, value|
|
35
|
-
Teaspoon.configuration.send("#{key.downcase}=", value) if Teaspoon.configuration.respond_to?("#{key.downcase}=")
|
36
|
-
end
|
37
|
-
end
|
42
|
+
private
|
38
43
|
|
39
44
|
def self.require_env(file)
|
40
|
-
|
45
|
+
::Kernel.load(file)
|
41
46
|
end
|
42
47
|
|
43
48
|
def self.rails_loaded?
|
44
49
|
defined?(Rails)
|
45
50
|
end
|
46
|
-
|
47
51
|
end
|
48
52
|
end
|
data/lib/teaspoon/exceptions.rb
CHANGED
@@ -1,7 +1,43 @@
|
|
1
1
|
module Teaspoon
|
2
|
-
class
|
3
|
-
class
|
4
|
-
class
|
5
|
-
class
|
6
|
-
class
|
2
|
+
class Error < Exception; end
|
3
|
+
class EnvironmentNotFound < Teaspoon::Error; end
|
4
|
+
class MissingDependency < Teaspoon::Error; end
|
5
|
+
class ServerException < Teaspoon::Error; end
|
6
|
+
class RunnerException < Teaspoon::Error; end
|
7
|
+
class ExporterException < Teaspoon::Error; end
|
8
|
+
class UnknownFramework < Teaspoon::Error; end
|
9
|
+
class UnknownDriver < Teaspoon::Error; end
|
10
|
+
class UnknownDriverOptions < Teaspoon::Error; end
|
11
|
+
class UnknownFormatter < Teaspoon::Error; end
|
12
|
+
class UnknownSuite < Teaspoon::Error; end
|
13
|
+
class AssetNotServable < Teaspoon::Error; end
|
14
|
+
class Failure < Teaspoon::Error; end
|
15
|
+
class DependencyFailure < Teaspoon::Error; end
|
16
|
+
class ThresholdNotMet < Teaspoon::Error; end
|
17
|
+
class FileNotWritable < Teaspoon::Error; end
|
18
|
+
|
19
|
+
module ExceptionHandling
|
20
|
+
|
21
|
+
def self.add_rails_handling
|
22
|
+
return unless Teaspoon.configuration.driver == "phantomjs"
|
23
|
+
|
24
|
+
#Rails.application.config.assets.debug = false # debugging should be off to display errors in the suite_controller
|
25
|
+
Rails.application.config.action_dispatch.show_exceptions = true # we want rails to display exceptions
|
26
|
+
|
27
|
+
# override the render exception method in ActionDispatch to raise a javascript exception
|
28
|
+
render_exceptions_with_javascript
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def self.render_exceptions_with_javascript
|
34
|
+
ActionDispatch::DebugExceptions.class_eval do
|
35
|
+
def render_exception(env, exception)
|
36
|
+
message = "#{exception.class.name}: #{exception.message}"
|
37
|
+
body = "<script>throw Error(#{[message, exception.backtrace].join("\n").inspect})</script>"
|
38
|
+
[200, {'Content-Type' => "text/html;", 'Content-Length' => body.bytesize.to_s}, [body]]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
7
43
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Teaspoon
|
2
|
+
class Exporter
|
3
|
+
include Teaspoon::Utility
|
4
|
+
|
5
|
+
def initialize(suite, url, output_path)
|
6
|
+
@suite = suite
|
7
|
+
@url = url
|
8
|
+
@output_path = File.join(File.expand_path(output_path || "export"), @suite.to_s)
|
9
|
+
end
|
10
|
+
|
11
|
+
def export
|
12
|
+
Dir.mktmpdir do |temp_path|
|
13
|
+
Dir.chdir(temp_path) do
|
14
|
+
%x{#{executable} --convert-links --adjust-extension --page-requisites --span-hosts #{@url.shellescape} 2>&1}
|
15
|
+
raise Teaspoon::ExporterException, "Unable to export #{@suite} suite." unless $?.exitstatus == 0
|
16
|
+
create_export(File.join(temp_path, @url.match(/^http:\/\/([^\/]+).*/)[1]))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def executable
|
24
|
+
return @executable if @executable
|
25
|
+
@executable = which("wget")
|
26
|
+
return @executable unless @executable.blank?
|
27
|
+
raise Teaspoon::MissingDependency, "Could not find wget for exporting."
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_export(path)
|
31
|
+
Dir.chdir(path) do
|
32
|
+
update_relative_paths
|
33
|
+
cleanup_output
|
34
|
+
move_output
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def update_relative_paths
|
39
|
+
html = File.read(".#{Teaspoon.configuration.mount_at}/#{@suite}.html")
|
40
|
+
File.write("index.html", html.gsub!('"../', '"'))
|
41
|
+
end
|
42
|
+
|
43
|
+
def cleanup_output
|
44
|
+
FileUtils.rm_r(Dir["{.#{Teaspoon.configuration.mount_at},robots.txt.html}"])
|
45
|
+
end
|
46
|
+
|
47
|
+
def move_output
|
48
|
+
FileUtils.mkdir_p(@output_path)
|
49
|
+
FileUtils.mv(Dir["*"], @output_path, force: true)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|