guard-jasmine 1.17.0 → 1.18.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 60fc1ca74efcf8df719d1d9943044e0ad59d51a3
4
- data.tar.gz: 24ef532486b920209d34741b4c7bce58b5ef8c53
3
+ metadata.gz: f8a880f0eac45a32232516339a2591ff56af0a4f
4
+ data.tar.gz: be38c7d0218b9354e3f4e84dd4683bc73ff7709b
5
5
  SHA512:
6
- metadata.gz: d62f8ea0aed0bbd2e856c1c7a9cf50fb43b9d8f9a92ca7a936a74136b7011c72b185955ccda13e07f9eadc4939c6eef02cda1278d71b6128dafa916116f725d5
7
- data.tar.gz: b5466cd09a10167866e6fa4c9ee439cb7afee8c420799b7747e182003b64faab1c910af3ba8e8165bfe06cf4213364ce64b616794088c3374ed9d5352c8fa059
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
@@ -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'
@@ -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[:jasmine_url] = options.url || "http://localhost:#{ runner_options[:port] }#{ options.server.to_sym == :jasmine_gem ? '/' : '/jasmine' }"
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
- page.evaluate ->
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
- return page.evaluate(function() {
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, "&amp;")
23
+ .replace(/</g, "&lt;")
24
+ .replace(/\>/g, "&gt;")
25
+ .replace(/\"/g, "&quot;")
26
+ .replace(/\'/g, "&apos;");
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++) {
@@ -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
- IO.popen("#{ phantomjs_command(options) } \"#{ suite }\" #{ options[:timeout] * 1000 } #{ options[:specdoc] } #{ options[:focus] } #{ options[:console] } #{ options[:errors] }", 'r:UTF-8')
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.
@@ -1,6 +1,6 @@
1
1
  module Guard
2
2
  module JasmineVersion
3
3
  # Guard::Jasmine version that is used for the Gem specification
4
- VERSION = '1.17.0'
4
+ VERSION = '1.18.0'
5
5
  end
6
6
  end
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.17.0
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-27 00:00:00.000000000 Z
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.2
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