guard-jasmine 1.17.0 → 1.18.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 +30 -1
- data/lib/guard/jasmine.rb +8 -2
- data/lib/guard/jasmine/cli.rb +25 -1
- data/lib/guard/jasmine/phantomjs/guard-jasmine.coffee +51 -2
- data/lib/guard/jasmine/phantomjs/guard-jasmine.js +81 -9
- data/lib/guard/jasmine/phantomjs/lib/console.js +1 -9
- data/lib/guard/jasmine/phantomjs/lib/junit_reporter.js +224 -0
- data/lib/guard/jasmine/phantomjs/lib/reporter.js +1 -5
- data/lib/guard/jasmine/phantomjs/lib/result.js +1 -9
- data/lib/guard/jasmine/runner.rb +13 -1
- data/lib/guard/jasmine/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8a880f0eac45a32232516339a2591ff56af0a4f
|
4
|
+
data.tar.gz: be38c7d0218b9354e3f4e84dd4683bc73ff7709b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43088c46d2ea7f7143c9ed9131cbc602ba0f38f82d8ad76c4444afbfe369d5ad0205621da86c91caed2b38a5ec6f61372f0486ee6a1b94473403a829efc07ec8
|
7
|
+
data.tar.gz: 5880051b4970b435a624ad4262a7df51f28e99b9573b16af012d0cd994221ca47623c0d4e2b734bfbf52b16ee1c9565ef555039e4fb13354256680354f25f360
|
data/README.md
CHANGED
@@ -15,7 +15,7 @@ Ruby.
|
|
15
15
|
* Fast headless testing on [PhantomJS][], a full featured WebKit browser with native support for
|
16
16
|
various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.
|
17
17
|
|
18
|
-
* Runs the standard Jasmine test runner, so you can use [Jasminerice][] for integrating [Jasmine][] into the
|
18
|
+
* Runs the standard Jasmine test runner, so you can use [Jasminerice][] or [jasmine-rails][] for integrating [Jasmine][] into the
|
19
19
|
[Rails asset pipeline][] and write your specs in [CoffeeScript][].
|
20
20
|
|
21
21
|
* Integrates [Istanbul](https://github.com/gotwarlost/istanbul) to instrument your code in the asset pipeline and
|
@@ -143,6 +143,34 @@ It also creates an empty `spec/javascripts/spec.css` file as it is always reques
|
|
143
143
|
|
144
144
|
Now you can access `/jasmine` when you start your Rails server normally.
|
145
145
|
|
146
|
+
### Jasmine-Rails
|
147
|
+
|
148
|
+
[jasmine-rails][] is another option for integrating your [Jasmine][] tests with an asset pipeline-enabled Rails application. The quick-and-dirty recipe for this is:
|
149
|
+
|
150
|
+
1. Add `jasmine-rails` to your `Gemfile`:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
group :test do
|
154
|
+
gem "jasmine-rails"
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
2. Configure a mount point in your application's `routes.rb` (please refer to the [jasmine-rails][] documentation for more details):
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
mount JasmineRails::Engine => '/spec' if defined?(JasmineRails)
|
162
|
+
```
|
163
|
+
|
164
|
+
3. Configure **Guard::Jasmine** to reference the mount point in your `Guardfile`:
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
guard 'jasmine', :server => :webrick, :server_mount => '/specs' do
|
168
|
+
# watch stuff
|
169
|
+
end
|
170
|
+
```
|
171
|
+
|
172
|
+
4. Profit! Seriously, you should be able to access the Jasmine runner at `/specs` within your Rails application, *and* **Guard::Jasmine** should run the same specs. Now no more excuses, get that javascript tested!
|
173
|
+
|
146
174
|
### Jasmine Stories acceptance tests
|
147
175
|
|
148
176
|
[Jasmine Stories](https://github.com/DominikGuzei/jasmine-stories) is a Jasminerice clone and that serves
|
@@ -884,6 +912,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
884
912
|
[PhantomJS build instructions]: http://code.google.com/p/phantomjs/wiki/BuildInstructions
|
885
913
|
[Brad Phelan]: http://twitter.com/#!/bradgonesurfing
|
886
914
|
[Jasminerice]: https://github.com/bradphelan/jasminerice
|
915
|
+
[jasmine-rails]: https://github.com/searls/jasmine-rails
|
887
916
|
[Pivotal Labs]: http://pivotallabs.com/
|
888
917
|
[Jasmine]: http://pivotal.github.com/jasmine/
|
889
918
|
[the Jasmine Gem]: https://github.com/pivotal/jasmine-gem
|
data/lib/guard/jasmine.rb
CHANGED
@@ -25,7 +25,7 @@ module Guard
|
|
25
25
|
server: :auto,
|
26
26
|
server_env: ENV['RAILS_ENV'] || 'development',
|
27
27
|
server_timeout: 60,
|
28
|
-
server_mount: '/jasmine',
|
28
|
+
server_mount: '/jasmine', # set here for documentation purposes; actually determiend at runtime by presence (or lack thereof) of the JasmineRails constant
|
29
29
|
port: nil,
|
30
30
|
rackup_config: nil,
|
31
31
|
jasmine_url: nil,
|
@@ -49,7 +49,10 @@ module Guard
|
|
49
49
|
statements_threshold: 0,
|
50
50
|
functions_threshold: 0,
|
51
51
|
branches_threshold: 0,
|
52
|
-
lines_threshold: 0
|
52
|
+
lines_threshold: 0,
|
53
|
+
junit: false,
|
54
|
+
junit_consolidate: true,
|
55
|
+
junit_save_path: ''
|
53
56
|
}
|
54
57
|
|
55
58
|
# Initialize Guard::Jasmine.
|
@@ -61,6 +64,7 @@ module Guard
|
|
61
64
|
# @option options [Integer] :server_timeout the number of seconds to wait for the Jasmine spec server
|
62
65
|
# @option options [String] :port the port for the Jasmine test server
|
63
66
|
# @option options [String] :rackup_config custom rackup config to use
|
67
|
+
# @option options [String] :server_mount custom mount point to use; defaults to '/specs' if JasmineRails is on the load path, otherwise '/jasmine'
|
64
68
|
# @option options [String] :jasmine_url the url of the Jasmine test runner
|
65
69
|
# @option options [String] :phantomjs_bin the location of the PhantomJS binary
|
66
70
|
# @option options [Integer] :timeout the maximum time in seconds to wait for the spec runner to finish
|
@@ -86,6 +90,8 @@ module Guard
|
|
86
90
|
# @option options [Hash] :run_all options overwrite options when run all specs
|
87
91
|
#
|
88
92
|
def initialize(watchers = [], options = { })
|
93
|
+
options[:server_mount] ||= defined?(JasmineRails) ? '/specs' : '/jasmine'
|
94
|
+
|
89
95
|
options = DEFAULT_OPTIONS.merge(options)
|
90
96
|
|
91
97
|
options[:spec_dir] ||= File.exists?(File.join('spec', 'javascripts')) ? File.join('spec', 'javascripts') : 'spec'
|
data/lib/guard/jasmine/cli.rb
CHANGED
@@ -70,6 +70,11 @@ module Guard
|
|
70
70
|
aliases: '-u',
|
71
71
|
desc: 'The url of the Jasmine test runner'
|
72
72
|
|
73
|
+
method_option :mount,
|
74
|
+
type: :string,
|
75
|
+
aliases: '-m',
|
76
|
+
desc: 'The mount point of the Jasmine test runner'
|
77
|
+
|
73
78
|
method_option :timeout,
|
74
79
|
type: :numeric,
|
75
80
|
aliases: '-t',
|
@@ -137,6 +142,21 @@ module Guard
|
|
137
142
|
default: 0,
|
138
143
|
desc: 'Lines coverage threshold'
|
139
144
|
|
145
|
+
method_option :junit,
|
146
|
+
type: :boolean,
|
147
|
+
default: false,
|
148
|
+
desc: 'Whether to save jasmine test results in JUnit-compatible xml files'
|
149
|
+
|
150
|
+
method_option :junit_consolidate,
|
151
|
+
type: :boolean,
|
152
|
+
default: false,
|
153
|
+
desc: 'Whether to save nested describes within the same xml file as their parent'
|
154
|
+
|
155
|
+
method_option :junit_save_path,
|
156
|
+
type: :string,
|
157
|
+
default: '',
|
158
|
+
desc: 'The directory to save junit xml files into'
|
159
|
+
|
140
160
|
# Run the Guard::Jasmine::Runner with options from
|
141
161
|
# the command line.
|
142
162
|
#
|
@@ -147,7 +167,8 @@ module Guard
|
|
147
167
|
runner_options[:port] = options.port || CLI.find_free_server_port
|
148
168
|
runner_options[:spec_dir] = options.spec_dir || (File.exists?(File.join('spec', 'javascripts')) ? File.join('spec', 'javascripts') : 'spec')
|
149
169
|
runner_options[:server] = options.server.to_sym == :auto ? ::Guard::Jasmine::Server.detect_server(runner_options[:spec_dir]) : options.server.to_sym
|
150
|
-
runner_options[:
|
170
|
+
runner_options[:server_mount] = options.mount || (defined?(JasmineRails) ? '/specs' : '/jasmine')
|
171
|
+
runner_options[:jasmine_url] = options.url || "http://localhost:#{ runner_options[:port] }#{ options.server.to_sym == :jasmine_gem ? '/' : runner_options[:server_mount] }"
|
151
172
|
runner_options[:phantomjs_bin] = options.bin || CLI.which('phantomjs')
|
152
173
|
runner_options[:timeout] = options.timeout
|
153
174
|
runner_options[:verbose] = options.verbose
|
@@ -169,6 +190,9 @@ module Guard
|
|
169
190
|
runner_options[:notification] = false
|
170
191
|
runner_options[:hide_success] = true
|
171
192
|
runner_options[:max_error_notify] = 0
|
193
|
+
runner_options[:junit] = options.junit
|
194
|
+
runner_options[:junit_consolidate] = options.junit_consolidate
|
195
|
+
runner_options[:junit_save_path] = options.junit_save_path
|
172
196
|
|
173
197
|
::Guard::UI.options = ::Guard::UI.options.merge({ :template => ':message' })
|
174
198
|
|
@@ -10,6 +10,9 @@ options =
|
|
10
10
|
focus: /true/i.test phantom.args[3]
|
11
11
|
console: phantom.args[4] || 'failure'
|
12
12
|
errors: phantom.args[5] || 'failure'
|
13
|
+
junit: /true/i.test phantom.args[6]
|
14
|
+
junit_consolidate: /true/i.test phantom.args[7]
|
15
|
+
junit_save_path: phantom.args[8] || ''
|
13
16
|
|
14
17
|
# Create the web page.
|
15
18
|
#
|
@@ -20,6 +23,8 @@ page = require('webpage').create()
|
|
20
23
|
currentSpecId = -1
|
21
24
|
logs = {}
|
22
25
|
errors = {}
|
26
|
+
resultsKey = "__jr" + Math.ceil(Math.random() * 1000000)
|
27
|
+
fs = require("fs")
|
23
28
|
|
24
29
|
# Catch JavaScript errors
|
25
30
|
#
|
@@ -47,18 +52,57 @@ page.onConsoleMessage = (msg, line, source) ->
|
|
47
52
|
# Initialize the page before the JavaScript is run.
|
48
53
|
#
|
49
54
|
page.onInitialized = ->
|
55
|
+
overloadPageEvaluate(page)
|
56
|
+
setupWriteFileFunction(page, resultsKey, fs.separator)
|
57
|
+
|
50
58
|
page.injectJs 'lib/console.js'
|
51
59
|
page.injectJs 'lib/reporter.js'
|
60
|
+
page.injectJs 'lib/junit_reporter.js'
|
52
61
|
|
53
|
-
|
62
|
+
setupReporters = ->
|
54
63
|
# Attach the console reporter when the document is ready.
|
55
64
|
window.onload = ->
|
56
65
|
window.onload = null
|
57
66
|
window.resultReceived = false
|
58
67
|
window.reporter = new ConsoleReporter()
|
59
68
|
if window.jasmine
|
69
|
+
jasmine.getEnv().addReporter(new JUnitXmlReporter("%save_path%", "%consolidate%"))
|
60
70
|
jasmine.getEnv().addReporter(window.reporter)
|
61
71
|
|
72
|
+
page.evaluate(setupReporters, {save_path: options.junit_save_path, consolidate: options.junit_consolidate})
|
73
|
+
|
74
|
+
|
75
|
+
getXmlResults = (page, key) ->
|
76
|
+
getWindowObj = ->
|
77
|
+
window["%resultsObj%"] || {}
|
78
|
+
page.evaluate getWindowObj, {resultsObj: key}
|
79
|
+
|
80
|
+
replaceFunctionPlaceholders= (fn, replacements) ->
|
81
|
+
if replacements && typeof replacements == 'object'
|
82
|
+
fn = fn.toString()
|
83
|
+
for p of replacements
|
84
|
+
if replacements.hasOwnProperty(p)
|
85
|
+
match = new RegExp("%" + p + "%", "g")
|
86
|
+
loop
|
87
|
+
fn = fn.replace(match, replacements[p])
|
88
|
+
break unless fn.indexOf(match) != -1
|
89
|
+
fn
|
90
|
+
|
91
|
+
overloadPageEvaluate = (page) ->
|
92
|
+
page._evaluate = page.evaluate
|
93
|
+
page.evaluate = (fn, replacements) ->
|
94
|
+
page._evaluate(replaceFunctionPlaceholders(fn, replacements))
|
95
|
+
page
|
96
|
+
|
97
|
+
setupWriteFileFunction= (page,key, path_separator) ->
|
98
|
+
saveData = () ->
|
99
|
+
window["%resultsObj%"] = {}
|
100
|
+
window.fs_path_separator = "%fs_path_separator%"
|
101
|
+
window.__phantom_writeFile = (filename, text) ->
|
102
|
+
window["%resultsObj%"][filename] = text;
|
103
|
+
|
104
|
+
page.evaluate saveData, {resultsObj: key, fs_path_separator: path_separator}
|
105
|
+
|
62
106
|
# Open web page and run the Jasmine test runner
|
63
107
|
#
|
64
108
|
page.open options.url, (status) ->
|
@@ -70,7 +114,6 @@ page.open options.url, (status) ->
|
|
70
114
|
else
|
71
115
|
waitFor jasmineReady, jasmineAvailable, options.timeout, jasmineMissing
|
72
116
|
|
73
|
-
|
74
117
|
# Test if the jasmine has been loaded
|
75
118
|
#
|
76
119
|
jasmineReady = ->
|
@@ -116,6 +159,12 @@ specsTimedout = ->
|
|
116
159
|
console.log JSON.stringify({ error: 'Timeout for the Jasmine test results!' })
|
117
160
|
|
118
161
|
specsDone = ->
|
162
|
+
if options.junit == true
|
163
|
+
xml_results = getXmlResults(page, resultsKey)
|
164
|
+
for filename of xml_results
|
165
|
+
if xml_results.hasOwnProperty(filename) && (output = xml_results[filename]) && typeof(output) == 'string'
|
166
|
+
fs.write(filename, output, 'w')
|
167
|
+
|
119
168
|
phantom.exit()
|
120
169
|
|
121
170
|
# Wait until the test condition is true or a timeout occurs.
|
@@ -1,5 +1,6 @@
|
|
1
|
+
// Generated by CoffeeScript 1.6.3
|
1
2
|
(function() {
|
2
|
-
var currentSpecId, errors, jasmineAvailable, jasmineMissing, jasmineReady, logs, options, page, specsDone, specsReady, specsTimedout, waitFor;
|
3
|
+
var currentSpecId, errors, fs, getXmlResults, jasmineAvailable, jasmineMissing, jasmineReady, logs, options, overloadPageEvaluate, page, replaceFunctionPlaceholders, resultsKey, setupWriteFileFunction, specsDone, specsReady, specsTimedout, waitFor;
|
3
4
|
|
4
5
|
phantom.injectJs('lib/result.js');
|
5
6
|
|
@@ -9,7 +10,10 @@
|
|
9
10
|
specdoc: phantom.args[2] || 'failure',
|
10
11
|
focus: /true/i.test(phantom.args[3]),
|
11
12
|
console: phantom.args[4] || 'failure',
|
12
|
-
errors: phantom.args[5] || 'failure'
|
13
|
+
errors: phantom.args[5] || 'failure',
|
14
|
+
junit: /true/i.test(phantom.args[6]),
|
15
|
+
junit_consolidate: /true/i.test(phantom.args[7]),
|
16
|
+
junit_save_path: phantom.args[8] || ''
|
13
17
|
};
|
14
18
|
|
15
19
|
page = require('webpage').create();
|
@@ -20,6 +24,10 @@
|
|
20
24
|
|
21
25
|
errors = {};
|
22
26
|
|
27
|
+
resultsKey = "__jr" + Math.ceil(Math.random() * 1000000);
|
28
|
+
|
29
|
+
fs = require("fs");
|
30
|
+
|
23
31
|
page.onError = function(msg, trace) {
|
24
32
|
if (currentSpecId) {
|
25
33
|
errors[currentSpecId] || (errors[currentSpecId] = []);
|
@@ -32,7 +40,6 @@
|
|
32
40
|
|
33
41
|
page.onConsoleMessage = function(msg, line, source) {
|
34
42
|
var result;
|
35
|
-
|
36
43
|
if (/^RUNNER_END$/.test(msg)) {
|
37
44
|
result = page.evaluate(function() {
|
38
45
|
return window.reporter.runnerResult;
|
@@ -50,17 +57,78 @@
|
|
50
57
|
};
|
51
58
|
|
52
59
|
page.onInitialized = function() {
|
60
|
+
var setupReporters;
|
61
|
+
overloadPageEvaluate(page);
|
62
|
+
setupWriteFileFunction(page, resultsKey, fs.separator);
|
53
63
|
page.injectJs('lib/console.js');
|
54
64
|
page.injectJs('lib/reporter.js');
|
55
|
-
|
65
|
+
page.injectJs('lib/junit_reporter.js');
|
66
|
+
setupReporters = function() {
|
56
67
|
return window.onload = function() {
|
57
68
|
window.onload = null;
|
58
69
|
window.resultReceived = false;
|
59
70
|
window.reporter = new ConsoleReporter();
|
60
71
|
if (window.jasmine) {
|
72
|
+
jasmine.getEnv().addReporter(new JUnitXmlReporter("%save_path%", "%consolidate%"));
|
61
73
|
return jasmine.getEnv().addReporter(window.reporter);
|
62
74
|
}
|
63
75
|
};
|
76
|
+
};
|
77
|
+
return page.evaluate(setupReporters, {
|
78
|
+
save_path: options.junit_save_path,
|
79
|
+
consolidate: options.junit_consolidate
|
80
|
+
});
|
81
|
+
};
|
82
|
+
|
83
|
+
getXmlResults = function(page, key) {
|
84
|
+
var getWindowObj;
|
85
|
+
getWindowObj = function() {
|
86
|
+
return window["%resultsObj%"] || {};
|
87
|
+
};
|
88
|
+
return page.evaluate(getWindowObj, {
|
89
|
+
resultsObj: key
|
90
|
+
});
|
91
|
+
};
|
92
|
+
|
93
|
+
replaceFunctionPlaceholders = function(fn, replacements) {
|
94
|
+
var match, p;
|
95
|
+
if (replacements && typeof replacements === 'object') {
|
96
|
+
fn = fn.toString();
|
97
|
+
for (p in replacements) {
|
98
|
+
if (replacements.hasOwnProperty(p)) {
|
99
|
+
match = new RegExp("%" + p + "%", "g");
|
100
|
+
while (true) {
|
101
|
+
fn = fn.replace(match, replacements[p]);
|
102
|
+
if (fn.indexOf(match) === -1) {
|
103
|
+
break;
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
return fn;
|
110
|
+
};
|
111
|
+
|
112
|
+
overloadPageEvaluate = function(page) {
|
113
|
+
page._evaluate = page.evaluate;
|
114
|
+
page.evaluate = function(fn, replacements) {
|
115
|
+
return page._evaluate(replaceFunctionPlaceholders(fn, replacements));
|
116
|
+
};
|
117
|
+
return page;
|
118
|
+
};
|
119
|
+
|
120
|
+
setupWriteFileFunction = function(page, key, path_separator) {
|
121
|
+
var saveData;
|
122
|
+
saveData = function() {
|
123
|
+
window["%resultsObj%"] = {};
|
124
|
+
window.fs_path_separator = "%fs_path_separator%";
|
125
|
+
return window.__phantom_writeFile = function(filename, text) {
|
126
|
+
return window["%resultsObj%"][filename] = text;
|
127
|
+
};
|
128
|
+
};
|
129
|
+
return page.evaluate(saveData, {
|
130
|
+
resultsObj: key,
|
131
|
+
fs_path_separator: path_separator
|
64
132
|
});
|
65
133
|
};
|
66
134
|
|
@@ -88,10 +156,8 @@
|
|
88
156
|
|
89
157
|
jasmineMissing = function() {
|
90
158
|
var error, text;
|
91
|
-
|
92
159
|
text = page.evaluate(function() {
|
93
160
|
var _ref;
|
94
|
-
|
95
161
|
return (_ref = document.getElementsByTagName('body')[0]) != null ? _ref.innerText : void 0;
|
96
162
|
});
|
97
163
|
if (text) {
|
@@ -114,10 +180,8 @@
|
|
114
180
|
|
115
181
|
specsTimedout = function() {
|
116
182
|
var error, text;
|
117
|
-
|
118
183
|
text = page.evaluate(function() {
|
119
184
|
var _ref;
|
120
|
-
|
121
185
|
return (_ref = document.getElementsByTagName('body')[0]) != null ? _ref.innerText : void 0;
|
122
186
|
});
|
123
187
|
if (text) {
|
@@ -133,12 +197,20 @@
|
|
133
197
|
};
|
134
198
|
|
135
199
|
specsDone = function() {
|
200
|
+
var filename, output, xml_results;
|
201
|
+
if (options.junit === true) {
|
202
|
+
xml_results = getXmlResults(page, resultsKey);
|
203
|
+
for (filename in xml_results) {
|
204
|
+
if (xml_results.hasOwnProperty(filename) && (output = xml_results[filename]) && typeof output === 'string') {
|
205
|
+
fs.write(filename, output, 'w');
|
206
|
+
}
|
207
|
+
}
|
208
|
+
}
|
136
209
|
return phantom.exit();
|
137
210
|
};
|
138
211
|
|
139
212
|
waitFor = function(test, ready, timeout, timeoutFunction) {
|
140
213
|
var condition, interval, start, wait;
|
141
|
-
|
142
214
|
if (timeout == null) {
|
143
215
|
timeout = 10000;
|
144
216
|
}
|
@@ -1,3 +1,4 @@
|
|
1
|
+
// Generated by CoffeeScript 1.6.3
|
1
2
|
(function() {
|
2
3
|
var Console,
|
3
4
|
__slice = [].slice;
|
@@ -5,35 +6,29 @@
|
|
5
6
|
Console = (function() {
|
6
7
|
function Console(console) {
|
7
8
|
var log;
|
8
|
-
|
9
9
|
log = console.log;
|
10
10
|
console.log = function() {
|
11
11
|
var args;
|
12
|
-
|
13
12
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
14
13
|
return log.call(console, Console.format.apply(Console, args));
|
15
14
|
};
|
16
15
|
console.info = function() {
|
17
16
|
var args;
|
18
|
-
|
19
17
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
20
18
|
return log.call(console, "INFO: " + (Console.format.apply(Console, args)));
|
21
19
|
};
|
22
20
|
console.warn = function() {
|
23
21
|
var args;
|
24
|
-
|
25
22
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
26
23
|
return log.call(console, "WARN: " + (Console.format.apply(Console, args)));
|
27
24
|
};
|
28
25
|
console.error = function() {
|
29
26
|
var args;
|
30
|
-
|
31
27
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
32
28
|
return log.call(console, "ERROR: " + (Console.format.apply(Console, args)));
|
33
29
|
};
|
34
30
|
console.debug = function() {
|
35
31
|
var args;
|
36
|
-
|
37
32
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
38
33
|
return log.call(console, "DEBUG: " + (Console.format.apply(Console, args)));
|
39
34
|
};
|
@@ -44,7 +39,6 @@
|
|
44
39
|
Console.format = function() {
|
45
40
|
var arg, args, result, _i, _len,
|
46
41
|
_this = this;
|
47
|
-
|
48
42
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
49
43
|
result = [];
|
50
44
|
if (typeof args[0] === 'string' && /%[sdifo]/gi.test(args[0])) {
|
@@ -62,7 +56,6 @@
|
|
62
56
|
|
63
57
|
Console.inspect = function(object, type) {
|
64
58
|
var match, result;
|
65
|
-
|
66
59
|
switch (type) {
|
67
60
|
case '%s':
|
68
61
|
result = String(object);
|
@@ -100,7 +93,6 @@
|
|
100
93
|
|
101
94
|
Console.pp = function(object, depth) {
|
102
95
|
var key, result, type, value, _i, _len;
|
103
|
-
|
104
96
|
if (depth == null) {
|
105
97
|
depth = 0;
|
106
98
|
}
|
@@ -0,0 +1,224 @@
|
|
1
|
+
(function() {
|
2
|
+
function elapsed(startTime, endTime) {
|
3
|
+
return (endTime - startTime)/1000;
|
4
|
+
}
|
5
|
+
|
6
|
+
function ISODateString(d) {
|
7
|
+
function pad(n) { return n < 10 ? '0'+n : n; }
|
8
|
+
|
9
|
+
return d.getFullYear() + '-' +
|
10
|
+
pad(d.getMonth()+1) + '-' +
|
11
|
+
pad(d.getDate()) + 'T' +
|
12
|
+
pad(d.getHours()) + ':' +
|
13
|
+
pad(d.getMinutes()) + ':' +
|
14
|
+
pad(d.getSeconds());
|
15
|
+
}
|
16
|
+
|
17
|
+
function trim(str) {
|
18
|
+
return str.replace(/^\s+/, "" ).replace(/\s+$/, "" );
|
19
|
+
}
|
20
|
+
|
21
|
+
function escapeInvalidXmlChars(str) {
|
22
|
+
return str.replace(/\&/g, "&")
|
23
|
+
.replace(/</g, "<")
|
24
|
+
.replace(/\>/g, ">")
|
25
|
+
.replace(/\"/g, """)
|
26
|
+
.replace(/\'/g, "'");
|
27
|
+
}
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Generates JUnit XML for the given spec run.
|
31
|
+
* Allows the test results to be used in java based CI
|
32
|
+
* systems like CruiseControl and Hudson.
|
33
|
+
*
|
34
|
+
* @param {string} savePath where to save the files
|
35
|
+
* @param {boolean} consolidate whether to save nested describes within the
|
36
|
+
* same file as their parent; default: true
|
37
|
+
* @param {boolean} useDotNotation whether to separate suite names with
|
38
|
+
* dots rather than spaces (ie "Class.init" not
|
39
|
+
* "Class init"); default: true
|
40
|
+
*/
|
41
|
+
var JUnitXmlReporter = function(savePath, consolidate, useDotNotation) {
|
42
|
+
this.savePath = savePath || '';
|
43
|
+
this.consolidate = consolidate === jasmine.undefined ? true : consolidate;
|
44
|
+
this.useDotNotation = useDotNotation === jasmine.undefined ? true : useDotNotation;
|
45
|
+
};
|
46
|
+
JUnitXmlReporter.finished_at = null; // will be updated after all files have been written
|
47
|
+
|
48
|
+
JUnitXmlReporter.prototype = {
|
49
|
+
reportSpecStarting: function(spec) {
|
50
|
+
spec.startTime = new Date();
|
51
|
+
|
52
|
+
if (!spec.suite.startTime) {
|
53
|
+
spec.suite.startTime = spec.startTime;
|
54
|
+
}
|
55
|
+
},
|
56
|
+
|
57
|
+
reportSpecResults: function(spec) {
|
58
|
+
var results = spec.results();
|
59
|
+
spec.didFail = !results.passed();
|
60
|
+
spec.duration = elapsed(spec.startTime, new Date());
|
61
|
+
spec.output = '<testcase classname="' + this.getFullName(spec.suite) +
|
62
|
+
'" name="' + escapeInvalidXmlChars(spec.description) + '" time="' + spec.duration + '">';
|
63
|
+
if(results.skipped) {
|
64
|
+
spec.output = spec.output + "<skipped />";
|
65
|
+
}
|
66
|
+
|
67
|
+
var failure = "";
|
68
|
+
var failures = 0;
|
69
|
+
var resultItems = results.getItems();
|
70
|
+
for (var i = 0; i < resultItems.length; i++) {
|
71
|
+
var result = resultItems[i];
|
72
|
+
|
73
|
+
if (result.type == 'expect' && result.passed && !result.passed()) {
|
74
|
+
failures += 1;
|
75
|
+
failure += '<failure type="' + result.type + '" message="' + trim(escapeInvalidXmlChars(result.message)) + '">';
|
76
|
+
failure += escapeInvalidXmlChars(result.trace.stack || result.message);
|
77
|
+
failure += "</failure>";
|
78
|
+
}
|
79
|
+
}
|
80
|
+
if (failure) {
|
81
|
+
spec.output += failure;
|
82
|
+
}
|
83
|
+
spec.output += "</testcase>";
|
84
|
+
},
|
85
|
+
|
86
|
+
reportSuiteResults: function(suite) {
|
87
|
+
var results = suite.results();
|
88
|
+
var specs = suite.specs();
|
89
|
+
var specOutput = "";
|
90
|
+
// for JUnit results, let's only include directly failed tests (not nested suites')
|
91
|
+
var failedCount = 0;
|
92
|
+
|
93
|
+
suite.status = results.passed() ? 'Passed.' : 'Failed.';
|
94
|
+
if (results.totalCount === 0) { // todo: change this to check results.skipped
|
95
|
+
suite.status = 'Skipped.';
|
96
|
+
}
|
97
|
+
|
98
|
+
// if a suite has no (active?) specs, reportSpecStarting is never called
|
99
|
+
// and thus the suite has no startTime -- account for that here
|
100
|
+
suite.startTime = suite.startTime || new Date();
|
101
|
+
suite.duration = elapsed(suite.startTime, new Date());
|
102
|
+
|
103
|
+
for (var i = 0; i < specs.length; i++) {
|
104
|
+
failedCount += specs[i].didFail ? 1 : 0;
|
105
|
+
specOutput += "\n " + specs[i].output;
|
106
|
+
}
|
107
|
+
suite.output = '\n<testsuite name="' + this.getFullName(suite) +
|
108
|
+
'" errors="0" tests="' + specs.length + '" failures="' + failedCount +
|
109
|
+
'" time="' + suite.duration + '" timestamp="' + ISODateString(suite.startTime) + '">';
|
110
|
+
suite.output += specOutput;
|
111
|
+
suite.output += "\n</testsuite>";
|
112
|
+
},
|
113
|
+
|
114
|
+
reportRunnerResults: function(runner) {
|
115
|
+
var suites = runner.suites();
|
116
|
+
for (var i = 0; i < suites.length; i++) {
|
117
|
+
var suite = suites[i];
|
118
|
+
var fileName = 'TEST-' + this.getFullName(suite, true) + '.xml';
|
119
|
+
var output = '<?xml version="1.0" encoding="UTF-8" ?>';
|
120
|
+
// if we are consolidating, only write out top-level suites
|
121
|
+
if (this.consolidate && suite.parentSuite) {
|
122
|
+
continue;
|
123
|
+
}
|
124
|
+
else if (this.consolidate) {
|
125
|
+
output += "\n<testsuites>";
|
126
|
+
output += this.getNestedOutput(suite);
|
127
|
+
output += "\n</testsuites>";
|
128
|
+
this.writeFile(this.savePath, fileName, output);
|
129
|
+
}
|
130
|
+
else {
|
131
|
+
output += suite.output;
|
132
|
+
this.writeFile(this.savePath, fileName, output);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
// When all done, make it known on JUnitXmlReporter
|
136
|
+
JUnitXmlReporter.finished_at = (new Date()).getTime();
|
137
|
+
},
|
138
|
+
|
139
|
+
getNestedOutput: function(suite) {
|
140
|
+
var output = suite.output;
|
141
|
+
for (var i = 0; i < suite.suites().length; i++) {
|
142
|
+
output += this.getNestedOutput(suite.suites()[i]);
|
143
|
+
}
|
144
|
+
return output;
|
145
|
+
},
|
146
|
+
|
147
|
+
writeFile: function(path, filename, text) {
|
148
|
+
function getQualifiedFilename(separator) {
|
149
|
+
if (path && path.substr(-1) !== separator && filename.substr(0) !== separator) {
|
150
|
+
path += separator;
|
151
|
+
}
|
152
|
+
return path + filename;
|
153
|
+
}
|
154
|
+
|
155
|
+
// Rhino
|
156
|
+
try {
|
157
|
+
// turn filename into a qualified path
|
158
|
+
if (path) {
|
159
|
+
filename = getQualifiedFilename(java.lang.System.getProperty("file.separator"));
|
160
|
+
// create parent dir and ancestors if necessary
|
161
|
+
var file = java.io.File(filename);
|
162
|
+
var parentDir = file.getParentFile();
|
163
|
+
if (!parentDir.exists()) {
|
164
|
+
parentDir.mkdirs();
|
165
|
+
}
|
166
|
+
}
|
167
|
+
// finally write the file
|
168
|
+
var out = new java.io.BufferedWriter(new java.io.FileWriter(filename));
|
169
|
+
out.write(text);
|
170
|
+
out.close();
|
171
|
+
return;
|
172
|
+
} catch (e) {}
|
173
|
+
// PhantomJS, via a method injected by phantomjs-testrunner.js
|
174
|
+
try {
|
175
|
+
// turn filename into a qualified path
|
176
|
+
filename = getQualifiedFilename(window.fs_path_separator);
|
177
|
+
__phantom_writeFile(filename, text);
|
178
|
+
return;
|
179
|
+
} catch (f) {}
|
180
|
+
// Node.js
|
181
|
+
try {
|
182
|
+
var fs = require("fs");
|
183
|
+
var nodejs_path = require("path");
|
184
|
+
var fd = fs.openSync(nodejs_path.join(path, filename), "w");
|
185
|
+
fs.writeSync(fd, text, 0);
|
186
|
+
fs.closeSync(fd);
|
187
|
+
return;
|
188
|
+
} catch (g) {}
|
189
|
+
},
|
190
|
+
|
191
|
+
getFullName: function(suite, isFilename) {
|
192
|
+
var fullName;
|
193
|
+
if (this.useDotNotation) {
|
194
|
+
fullName = suite.description;
|
195
|
+
for (var parentSuite = suite.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
|
196
|
+
fullName = parentSuite.description + '.' + fullName;
|
197
|
+
}
|
198
|
+
}
|
199
|
+
else {
|
200
|
+
fullName = suite.getFullName();
|
201
|
+
}
|
202
|
+
|
203
|
+
// Either remove or escape invalid XML characters
|
204
|
+
if (isFilename) {
|
205
|
+
return fullName.replace(/[^\w]/g, "");
|
206
|
+
}
|
207
|
+
return escapeInvalidXmlChars(fullName);
|
208
|
+
},
|
209
|
+
|
210
|
+
log: function(str) {
|
211
|
+
var console = jasmine.getGlobal().console;
|
212
|
+
|
213
|
+
if (console && console.log) {
|
214
|
+
console.log(str);
|
215
|
+
}
|
216
|
+
}
|
217
|
+
};
|
218
|
+
|
219
|
+
if (typeof module !== 'undefined' && module.exports) {
|
220
|
+
module.exports = JUnitXmlReporter;
|
221
|
+
} else {
|
222
|
+
window.JUnitXmlReporter = JUnitXmlReporter;
|
223
|
+
}
|
224
|
+
}).call(this);
|
@@ -1,3 +1,4 @@
|
|
1
|
+
// Generated by CoffeeScript 1.6.3
|
1
2
|
(function() {
|
2
3
|
var ConsoleReporter;
|
3
4
|
|
@@ -26,7 +27,6 @@
|
|
26
27
|
|
27
28
|
ConsoleReporter.prototype.reportSpecResults = function(spec) {
|
28
29
|
var messages, result, specResult, _base, _i, _len, _name, _ref;
|
29
|
-
|
30
30
|
if (!spec.results().skipped) {
|
31
31
|
specResult = {
|
32
32
|
id: spec.id,
|
@@ -52,7 +52,6 @@
|
|
52
52
|
|
53
53
|
ConsoleReporter.prototype.reportSuiteResults = function(suite) {
|
54
54
|
var parent, suiteResult, _base, _ref;
|
55
|
-
|
56
55
|
if (!suite.results().skipped) {
|
57
56
|
suiteResult = {
|
58
57
|
id: suite.id,
|
@@ -78,7 +77,6 @@
|
|
78
77
|
|
79
78
|
ConsoleReporter.prototype.reportRunnerResults = function(runner) {
|
80
79
|
var end, runtime;
|
81
|
-
|
82
80
|
runtime = (new Date().getTime() - this.startTime) / 1000;
|
83
81
|
this.runnerResult['passed'] = runner.results().failedCount === 0;
|
84
82
|
this.runnerResult['stats'] = {
|
@@ -101,7 +99,6 @@
|
|
101
99
|
|
102
100
|
ConsoleReporter.prototype.addNestedSuites = function(suiteResult) {
|
103
101
|
var suite, _i, _len, _ref, _results;
|
104
|
-
|
105
102
|
if (this.nestedSuiteResults[suiteResult.id]) {
|
106
103
|
_ref = this.nestedSuiteResults[suiteResult.id];
|
107
104
|
_results = [];
|
@@ -116,7 +113,6 @@
|
|
116
113
|
|
117
114
|
ConsoleReporter.prototype.removeEmptySuites = function(suiteResult) {
|
118
115
|
var suite, suites, _i, _len, _ref;
|
119
|
-
|
120
116
|
suites = [];
|
121
117
|
_ref = suiteResult.suites;
|
122
118
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
@@ -1,3 +1,4 @@
|
|
1
|
+
// Generated by CoffeeScript 1.6.3
|
1
2
|
(function() {
|
2
3
|
var Result;
|
3
4
|
|
@@ -11,10 +12,8 @@
|
|
11
12
|
|
12
13
|
Result.prototype.addLogs = function(suite) {
|
13
14
|
var id, s, spec;
|
14
|
-
|
15
15
|
suite.suites = (function() {
|
16
16
|
var _i, _len, _ref, _results;
|
17
|
-
|
18
17
|
_ref = suite.suites;
|
19
18
|
_results = [];
|
20
19
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
@@ -26,7 +25,6 @@
|
|
26
25
|
if (suite.specs) {
|
27
26
|
suite.specs = (function() {
|
28
27
|
var _i, _len, _ref, _results;
|
29
|
-
|
30
28
|
_ref = suite.specs;
|
31
29
|
_results = [];
|
32
30
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
@@ -47,10 +45,8 @@
|
|
47
45
|
|
48
46
|
Result.prototype.addErrors = function(suite) {
|
49
47
|
var id, s, spec;
|
50
|
-
|
51
48
|
suite.suites = (function() {
|
52
49
|
var _i, _len, _ref, _results;
|
53
|
-
|
54
50
|
_ref = suite.suites;
|
55
51
|
_results = [];
|
56
52
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
@@ -62,7 +58,6 @@
|
|
62
58
|
if (suite.specs) {
|
63
59
|
suite.specs = (function() {
|
64
60
|
var _i, _len, _ref, _results;
|
65
|
-
|
66
61
|
_ref = suite.specs;
|
67
62
|
_results = [];
|
68
63
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
@@ -83,7 +78,6 @@
|
|
83
78
|
|
84
79
|
Result.prototype.addGlobalError = function(suite) {
|
85
80
|
var b, err, errMsg, globalErrors, noSpecs, noSuites, _i, _len, _ref;
|
86
|
-
|
87
81
|
noSuites = !suite.suites || suite.suites.length === 0;
|
88
82
|
noSpecs = !suite.specs || suite.specs.length === 0;
|
89
83
|
globalErrors = this.errors[-1] && this.errors[-1].length !== 0;
|
@@ -102,10 +96,8 @@
|
|
102
96
|
|
103
97
|
Result.prototype.cleanResult = function(suite) {
|
104
98
|
var s, spec, _i, _len, _ref;
|
105
|
-
|
106
99
|
suite.suites = (function() {
|
107
100
|
var _i, _len, _ref, _results;
|
108
|
-
|
109
101
|
_ref = suite.suites;
|
110
102
|
_results = [];
|
111
103
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
data/lib/guard/jasmine/runner.rb
CHANGED
@@ -94,7 +94,19 @@ module Guard
|
|
94
94
|
def run_jasmine_spec(file, options)
|
95
95
|
suite = jasmine_suite(file, options)
|
96
96
|
Formatter.info("Run Jasmine suite at #{ suite }")
|
97
|
-
|
97
|
+
|
98
|
+
arguments = [
|
99
|
+
options[:timeout] * 1000,
|
100
|
+
options[:specdoc],
|
101
|
+
options[:focus],
|
102
|
+
options[:console],
|
103
|
+
options[:errors],
|
104
|
+
options[:junit],
|
105
|
+
options[:junit_consolidate],
|
106
|
+
"'#{ options[:junit_save_path] }'"
|
107
|
+
]
|
108
|
+
|
109
|
+
IO.popen("#{ phantomjs_command(options) } \"#{ suite }\" #{ arguments.collect { |i| i.to_s }.join(' ')}", 'r:UTF-8')
|
98
110
|
end
|
99
111
|
|
100
112
|
# Get the PhantomJS binary and script to execute.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: guard-jasmine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.18.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Kessler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-06
|
11
|
+
date: 2013-08-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: guard
|
@@ -112,6 +112,7 @@ files:
|
|
112
112
|
- lib/guard/jasmine/phantomjs/guard-jasmine.coffee
|
113
113
|
- lib/guard/jasmine/phantomjs/guard-jasmine.js
|
114
114
|
- lib/guard/jasmine/phantomjs/lib/console.js
|
115
|
+
- lib/guard/jasmine/phantomjs/lib/junit_reporter.js
|
115
116
|
- lib/guard/jasmine/phantomjs/lib/reporter.js
|
116
117
|
- lib/guard/jasmine/phantomjs/lib/result.js
|
117
118
|
- lib/guard/jasmine/phantomjs/src/console.coffee
|
@@ -148,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
149
|
version: 1.3.6
|
149
150
|
requirements: []
|
150
151
|
rubyforge_project: guard-jasmine
|
151
|
-
rubygems_version: 2.0.
|
152
|
+
rubygems_version: 2.0.3
|
152
153
|
signing_key:
|
153
154
|
specification_version: 4
|
154
155
|
summary: Guard gem for headless testing with Jasmine
|