guard-jasmine 1.0.4 → 1.1.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.
data/README.md CHANGED
@@ -314,9 +314,6 @@ The spec runner options configures the behavior driven development (or BDD) cycl
314
314
  :all_on_start => false # Run all suites on start.
315
315
  # default: true
316
316
 
317
- :all_on_start => false # Run all suites on start.
318
- # default: true
319
-
320
317
  :keep_failed => false # Keep failed suites and add them to the next run again.
321
318
  # default: true
322
319
 
@@ -351,6 +348,10 @@ be shown in the console:
351
348
  :console => :always # Console.log output options,
352
349
  # either :always, :never or :failure
353
350
  # default: :failure
351
+
352
+ :errors => :always # Error output options,
353
+ # either :always, :never or :failure
354
+ # default: :failure
354
355
  ```
355
356
 
356
357
  With the option set to `:always`, the specdoc is shown with and without errors in your spec, whereas on with the option
@@ -359,6 +360,10 @@ set to `:never`, there is no output at all, instead just a summary of the spec r
359
360
 
360
361
  When `:focus` is enabled, only the failing specs are shown in the specdoc when at least one spec is failing.
361
362
 
363
+ The `:errors` option is partially working when using at least PhantomJS version 1.5. Please see
364
+ [Issue #166](http://code.google.com/p/phantomjs/issues/detail?id=166) for the actual status of retreiving the JavaScript
365
+ stack trace.
366
+
362
367
  <a name="console-logs" />
363
368
  #### Console logs
364
369
 
@@ -454,6 +459,9 @@ Options:
454
459
  -c, [--console=CONSOLE] # Whether to show console.log statements in the spec runner,
455
460
  # either `always`, `never` or `failure`
456
461
  # Default: failure
462
+ -x, [--errors=ERRORS] # Whether to show errors in the spec runner,
463
+ # either `always`, `never` or `failure`
464
+ # Default: failure
457
465
  -e, [--server-env=SERVER_ENV] # The server environment to use, for example `development`, `test`
458
466
  # Default: test
459
467
 
@@ -504,12 +512,17 @@ script: 'bundle exec guard-jasmine'
504
512
 
505
513
  You can also run your Guard::Jasmine specs after your specs that are ran with `rake` by using `after_script`:
506
514
 
515
+ ```yaml
516
+ script: 'rake spec'
517
+ after_script: 'bundle exec guard-jasmine'
518
+ ```
519
+
520
+ When using a PhantomJS version prior to 1.5, you need to start `xvfb` before running the specs:
521
+
507
522
  ```yaml
508
523
  before_script:
509
524
  - "export DISPLAY=:99.0"
510
525
  - "sh -e /etc/init.d/xvfb start"
511
- script: 'rake spec'
512
- after_script: 'bundle exec guard-jasmine'
513
526
  ```
514
527
 
515
528
  ## Alternatives
@@ -36,6 +36,7 @@ module Guard
36
36
  :max_error_notify => 3,
37
37
  :specdoc => :failure,
38
38
  :console => :failure,
39
+ :errors => :failure,
39
40
  :focus => true
40
41
  }
41
42
 
@@ -59,6 +60,7 @@ module Guard
59
60
  # @option options [Boolean] :all_after_pass run all suites after a suite has passed again after failing
60
61
  # @option options [Symbol] :specdoc options for the specdoc output, either :always, :never or :failure
61
62
  # @option options [Symbol] :console options for the console.log output, either :always, :never or :failure
63
+ # @option options [Symbol] :errors options for the errors output, either :always, :never or :failure
62
64
  # @option options [Symbol] :focus options for focus on failures in the specdoc
63
65
  #
64
66
  def initialize(watchers = [], options = { })
@@ -57,6 +57,12 @@ module Guard
57
57
  :default => 'failure',
58
58
  :desc => 'Whether to show console.log statements in the spec runner, either `always`, `never` or `failure`'
59
59
 
60
+ method_option :errors,
61
+ :type => :string,
62
+ :aliases => '-x',
63
+ :default => 'failure',
64
+ :desc => 'Whether to show errors in the spec runner, either `always`, `never` or `failure`'
65
+
60
66
  method_option :server_env,
61
67
  :type => :string,
62
68
  :aliases => '-e',
@@ -85,6 +91,7 @@ module Guard
85
91
  runner[:server_env] = options.server_env
86
92
  runner[:spec_dir] = options.spec_dir
87
93
  runner[:console] = [:always, :never, :failure].include?(options.console.to_sym) ? options.console.to_sym : :failure
94
+ runner[:errors] = [:always, :never, :failure].include?(options.errors.to_sym) ? options.errors.to_sym : :failure
88
95
  runner[:server] = options.server.to_sym
89
96
 
90
97
  runner[:notification] = false
@@ -1,9 +1,15 @@
1
1
  # This file is the script that runs within PhantomJS, requests the Jasmine specs
2
2
  # and waits until they are ready.
3
+ phantom.injectJs 'lib/result.js'
3
4
 
4
5
  # Set default values
5
- url = phantom.args[0] || 'http://127.0.0.1:3000/jasmine'
6
- timeout = parseInt(phantom.args[1] || 5000)
6
+ options =
7
+ url: phantom.args[0] || 'http://127.0.0.1:3000/jasmine'
8
+ timeout: parseInt(phantom.args[1] || 5000)
9
+ specdoc: phantom.args[2] || 'failure'
10
+ focus: /true/i.test phantom.args[3]
11
+ console: phantom.args[4] || 'failure'
12
+ errors: phantom.args[5] || 'failure'
7
13
 
8
14
  # Create the web page.
9
15
  #
@@ -13,22 +19,14 @@ page = require('webpage').create()
13
19
  #
14
20
  currentSpecId = -1
15
21
  logs = {}
22
+ errors = {}
16
23
 
17
- # Add logs to the given suite
24
+ # Catch JavaScript errors
18
25
  #
19
- # @param suite [Object} the suite result
20
- #
21
- page.addLogs = (suite) ->
22
- for s in suite.suites
23
- arguments.callee(s) if s
24
-
25
- for spec in suite.specs
26
- id = Number(spec['id'])
27
- spec['logs'] = logs[id] if logs[id] && logs[id].length isnt 0
28
- delete spec['id']
29
-
30
- delete suite['id']
31
- delete suite['parent']
26
+ page.onError = (msg, trace) ->
27
+ if currentSpecId && currentSpecId isnt -1
28
+ errors[currentSpecId] ||= []
29
+ errors[currentSpecId].push({ msg: msg, trace: trace })
32
30
 
33
31
  # Capture console.log output to add it to
34
32
  # the result when specs have finished.
@@ -36,12 +34,7 @@ page.addLogs = (suite) ->
36
34
  page.onConsoleMessage = (msg, line, source) ->
37
35
  if /^RUNNER_END$/.test(msg)
38
36
  result = page.evaluate -> window.reporter.runnerResult
39
-
40
- for suite in result.suites
41
- page.addLogs(suite)
42
-
43
- console.log JSON.stringify(result)
44
-
37
+ console.log JSON.stringify(new Result(result, logs, errors, options).process())
45
38
  page.evaluate -> window.resultReceived = true
46
39
 
47
40
  else if /^SPEC_START: (\d+)$/.test(msg)
@@ -66,16 +59,16 @@ page.onInitialized = ->
66
59
 
67
60
  # Open web page and run the Jasmine test runner
68
61
  #
69
- page.open url, (status) ->
62
+ page.open options.url, (status) ->
70
63
  # Avoid that a failed iframe load breaks the runner, see https://github.com/netzpirat/guard-jasmine/pull/19
71
64
  page.onLoadFinished = ->
72
65
 
73
66
  if status isnt 'success'
74
- console.log JSON.stringify({ error: "Unable to access Jasmine specs at #{ url }" })
67
+ console.log JSON.stringify({ error: "Unable to access Jasmine specs at #{ options.url }" })
75
68
  phantom.exit()
76
69
  else
77
70
  done = -> phantom.exit()
78
- waitFor specsReady, done, timeout
71
+ waitFor specsReady, done, options.timeout
79
72
 
80
73
  # Test if the specs have finished.
81
74
  #
@@ -76,7 +76,7 @@
76
76
  };
77
77
 
78
78
  ConsoleReporter.prototype.reportRunnerResults = function(runner) {
79
- var runtime;
79
+ var end, runtime;
80
80
  runtime = (new Date().getTime() - this.startTime) / 1000;
81
81
  this.runnerResult['passed'] = runner.results().failedCount === 0;
82
82
  this.runnerResult['stats'] = {
@@ -84,7 +84,10 @@
84
84
  failures: runner.results().failedCount,
85
85
  time: runtime
86
86
  };
87
- return console.log("RUNNER_END");
87
+ end = function() {
88
+ return console.log("RUNNER_END");
89
+ };
90
+ return setTimeout(end, 10);
88
91
  };
89
92
 
90
93
  ConsoleReporter.prototype.reportRunnerStarting = function(runner) {
@@ -0,0 +1,120 @@
1
+ (function() {
2
+ var Result;
3
+
4
+ Result = (function() {
5
+
6
+ function Result(result, logs, errors, options) {
7
+ this.result = result;
8
+ this.logs = logs != null ? logs : {};
9
+ this.errors = errors != null ? errors : {};
10
+ this.options = options != null ? options : {};
11
+ }
12
+
13
+ Result.prototype.addLogs = function(suite) {
14
+ var id, s, spec;
15
+ suite.suites = (function() {
16
+ var _i, _len, _ref, _results;
17
+ _ref = suite.suites;
18
+ _results = [];
19
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
20
+ s = _ref[_i];
21
+ _results.push(this.addLogs(s));
22
+ }
23
+ return _results;
24
+ }).call(this);
25
+ if (suite.specs) {
26
+ suite.specs = (function() {
27
+ var _i, _len, _ref, _results;
28
+ _ref = suite.specs;
29
+ _results = [];
30
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
31
+ spec = _ref[_i];
32
+ if (this.options.console === 'always' || (this.options.console === 'failure' && !spec.passed)) {
33
+ id = Number(spec['id']);
34
+ if (this.logs[id] && this.logs[id].length !== 0) {
35
+ spec.logs = this.logs[id];
36
+ }
37
+ }
38
+ _results.push(spec);
39
+ }
40
+ return _results;
41
+ }).call(this);
42
+ }
43
+ return suite;
44
+ };
45
+
46
+ Result.prototype.addErrors = function(suite) {
47
+ var id, s, spec;
48
+ suite.suites = (function() {
49
+ var _i, _len, _ref, _results;
50
+ _ref = suite.suites;
51
+ _results = [];
52
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
53
+ s = _ref[_i];
54
+ _results.push(this.addErrors(s));
55
+ }
56
+ return _results;
57
+ }).call(this);
58
+ if (suite.specs) {
59
+ suite.specs = (function() {
60
+ var _i, _len, _ref, _results;
61
+ _ref = suite.specs;
62
+ _results = [];
63
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
64
+ spec = _ref[_i];
65
+ if (this.options.errors === 'always' || (this.options.errors === 'failure' && !spec.passed)) {
66
+ id = Number(spec['id']);
67
+ if (this.errors[id] && this.errors[id].length !== 0) {
68
+ spec.errors = this.errors[id];
69
+ }
70
+ }
71
+ _results.push(spec);
72
+ }
73
+ return _results;
74
+ }).call(this);
75
+ }
76
+ return suite;
77
+ };
78
+
79
+ Result.prototype.cleanResult = function(suite) {
80
+ var s, spec, _i, _len, _ref;
81
+ suite.suites = (function() {
82
+ var _i, _len, _ref, _results;
83
+ _ref = suite.suites;
84
+ _results = [];
85
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
86
+ s = _ref[_i];
87
+ _results.push(this.cleanResult(s));
88
+ }
89
+ return _results;
90
+ }).call(this);
91
+ if (suite.specs) {
92
+ _ref = suite.specs;
93
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
94
+ spec = _ref[_i];
95
+ delete spec['id'];
96
+ }
97
+ }
98
+ delete suite['id'];
99
+ delete suite['parent'];
100
+ return suite;
101
+ };
102
+
103
+ Result.prototype.process = function() {
104
+ if (this.options.console !== 'never') this.addLogs(this.result);
105
+ if (this.options.errors !== 'never') this.addErrors(this.result);
106
+ this.cleanResult(this.result);
107
+ return this.result;
108
+ };
109
+
110
+ return Result;
111
+
112
+ })();
113
+
114
+ if (typeof module !== 'undefined' && module.exports) {
115
+ if (module) module.exports = Result;
116
+ } else {
117
+ if (window) window.Result = Result;
118
+ }
119
+
120
+ }).call(this);
@@ -1,4 +1,4 @@
1
- # Simplified console logger rreplacement.
1
+ # Simplified console logger replacement.
2
2
  #
3
3
  class Console
4
4
 
@@ -87,7 +87,9 @@ class ConsoleReporter
87
87
  time: runtime
88
88
  }
89
89
 
90
- console.log "RUNNER_END"
90
+ # Delay the end runner message, so that logs and errors can be retreived in between
91
+ end = -> console.log "RUNNER_END"
92
+ setTimeout end, 10
91
93
 
92
94
  # Report the start of the runner
93
95
  #
@@ -0,0 +1,79 @@
1
+ # Combines various information into the final result set
2
+ # that will be outputted to the console.
3
+ #
4
+ class Result
5
+
6
+ # Construct the result parser
7
+ #
8
+ constructor: (@result, @logs = {}, @errors = {}, @options = {}) ->
9
+
10
+ # Add captured log statements to the result
11
+ #
12
+ # @param [Object] suite the suite result
13
+ # @return [Object] the suite
14
+ #
15
+ addLogs: (suite) ->
16
+ suite.suites = for s in suite.suites
17
+ @addLogs(s)
18
+
19
+ if suite.specs
20
+ suite.specs = for spec in suite.specs
21
+ if @options.console is 'always' || (@options.console is 'failure' && !spec.passed)
22
+ id = Number(spec['id'])
23
+ spec.logs = @logs[id] if @logs[id] && @logs[id].length isnt 0
24
+
25
+ spec
26
+
27
+ suite
28
+
29
+ # Add captured errors to the result
30
+ #
31
+ # @param [Object] suite the suite result
32
+ # @return [Object] the suite
33
+ #
34
+ addErrors: (suite) ->
35
+ suite.suites = for s in suite.suites
36
+ @addErrors(s)
37
+
38
+ if suite.specs
39
+ suite.specs = for spec in suite.specs
40
+ if @options.errors is 'always' || (@options.errors is 'failure' && !spec.passed)
41
+ id = Number(spec['id'])
42
+ spec.errors = @errors[id] if @errors[id] && @errors[id].length isnt 0
43
+
44
+ spec
45
+
46
+ suite
47
+
48
+ # Clean unnecessary properties from the result
49
+ #
50
+ # @param [Object] suite the suite result
51
+ # @return [Object] the cleaned suite
52
+ #
53
+ cleanResult: (suite) ->
54
+ suite.suites = for s in suite.suites
55
+ @cleanResult(s)
56
+
57
+ if suite.specs
58
+ delete spec['id'] for spec in suite.specs
59
+
60
+ delete suite['id']
61
+ delete suite['parent']
62
+
63
+ suite
64
+
65
+ # Writes the result output to the console.
66
+ #
67
+ # @return [Object] the Jasmine result
68
+ #
69
+ process: ->
70
+ @addLogs(@result) if @options.console isnt 'never'
71
+ @addErrors(@result) if @options.errors isnt 'never'
72
+ @cleanResult(@result)
73
+
74
+ @result
75
+
76
+ if typeof module isnt 'undefined' and module.exports
77
+ module.exports = Result if module
78
+ else
79
+ window.Result = Result if window
@@ -3,7 +3,7 @@ sinon = require 'sinon'
3
3
 
4
4
  Console = require '../src/console'
5
5
 
6
- describe 'console', ->
6
+ describe 'Console', ->
7
7
  beforeEach ->
8
8
  @log = sinon.stub()
9
9
  @console = { log: @log }
@@ -0,0 +1,311 @@
1
+ sinon = require 'sinon'
2
+ {expect} = require 'chai'
3
+
4
+ Result = require '../src/result'
5
+
6
+ describe 'Result', ->
7
+ beforeEach ->
8
+ @logObj =
9
+ 0: ['Log 1', 'Another Log']
10
+ 1: ['Log 2']
11
+ 3: ['Log 4', 'more Logs']
12
+
13
+ @errorsObj =
14
+ 1: [{ msg: 'Failure 1', trace: { file: 'a file' }}]
15
+ 2: [{ msg: 'Failure 2', trace: { file: 'another file' }}]
16
+ 3: [{ msg: 'Failure 3', trace: { file: 'file' }}]
17
+
18
+ @resultObj =
19
+ passed: false
20
+ stats:
21
+ failures: 1
22
+ specs: 4
23
+ time: 0.10
24
+ specs: [
25
+ {
26
+ description: "Spec 1"
27
+ id: 0
28
+ passed: true
29
+ }
30
+ ]
31
+ suites: [
32
+ {
33
+ description: "Suite 1"
34
+ id: 0
35
+ passed: true
36
+ specs: [
37
+ {
38
+ description: "Spec 2"
39
+ id: 1
40
+ passed: true
41
+ }
42
+ {
43
+ description: "Spec 3"
44
+ id: 2
45
+ passed: true
46
+ }
47
+ ]
48
+ suites: [
49
+ description: "Suite 2"
50
+ id: 1
51
+ passed: false
52
+ specs: [
53
+ {
54
+ description: "Spec 4"
55
+ id: 3
56
+ passed: false
57
+ }
58
+ ]
59
+ suites: []
60
+ ]
61
+ }
62
+ ]
63
+
64
+ describe '#prepare', ->
65
+ describe 'when console and errors are :never', ->
66
+ beforeEach ->
67
+ @result = new Result(@resultObj, @logObj, @errorsObj, { console: 'never', errors: 'never' }).process()
68
+
69
+ it 'does not add the log and error statements to the specs', ->
70
+ expected = {
71
+ passed: false
72
+ stats:
73
+ failures: 1
74
+ specs: 4
75
+ time: 0.10
76
+ specs: [
77
+ {
78
+ description: "Spec 1"
79
+ passed: true
80
+ }
81
+ ]
82
+ suites: [
83
+ {
84
+ description: "Suite 1"
85
+ passed: true
86
+ specs: [
87
+ {
88
+ description: "Spec 2"
89
+ passed: true
90
+ }
91
+ {
92
+ description: "Spec 3"
93
+ passed: true
94
+ }
95
+ ]
96
+ suites: [
97
+ description: "Suite 2"
98
+ passed: false
99
+ specs: [
100
+ {
101
+ description: "Spec 4"
102
+ passed: false
103
+ }
104
+ ]
105
+ suites: []
106
+ ]
107
+ }
108
+ ]
109
+ }
110
+
111
+ expect(@result).to.eql expected
112
+
113
+ describe 'when console is :always', ->
114
+ beforeEach ->
115
+ @result = new Result(@resultObj, @logObj, @errorsObj, { console: 'always', errors: 'never' }).process()
116
+
117
+ it 'does add all the log statements to the specs', ->
118
+ expected = {
119
+ passed: false
120
+ stats:
121
+ failures: 1
122
+ specs: 4
123
+ time: 0.10
124
+ specs: [
125
+ {
126
+ description: "Spec 1"
127
+ passed: true
128
+ logs: ['Log 1', 'Another Log']
129
+ }
130
+ ]
131
+ suites: [
132
+ {
133
+ description: "Suite 1"
134
+ passed: true
135
+ specs: [
136
+ {
137
+ description: "Spec 2"
138
+ passed: true
139
+ logs: ['Log 2']
140
+ }
141
+ {
142
+ description: "Spec 3"
143
+ passed: true
144
+ }
145
+ ]
146
+ suites: [
147
+ description: "Suite 2"
148
+ passed: false
149
+ specs: [
150
+ {
151
+ description: "Spec 4"
152
+ passed: false
153
+ logs: ['Log 4', 'more Logs']
154
+ }
155
+ ]
156
+ suites: []
157
+ ]
158
+ }
159
+ ]
160
+ }
161
+
162
+ expect(@result).to.eql expected
163
+
164
+ describe 'when console is :failure', ->
165
+ beforeEach ->
166
+ @result = new Result(@resultObj, @logObj, @errorsObj, { console: 'failure', errors: 'never' }).process()
167
+
168
+ it 'does add the log statements to the failing specs', ->
169
+ expected = {
170
+ passed: false
171
+ stats:
172
+ failures: 1
173
+ specs: 4
174
+ time: 0.10
175
+ specs: [
176
+ {
177
+ description: "Spec 1"
178
+ passed: true
179
+ }
180
+ ]
181
+ suites: [
182
+ {
183
+ description: "Suite 1"
184
+ passed: true
185
+ specs: [
186
+ {
187
+ description: "Spec 2"
188
+ passed: true
189
+ }
190
+ {
191
+ description: "Spec 3"
192
+ passed: true
193
+ }
194
+ ]
195
+ suites: [
196
+ description: "Suite 2"
197
+ passed: false
198
+ specs: [
199
+ {
200
+ description: "Spec 4"
201
+ passed: false
202
+ logs: ['Log 4', 'more Logs']
203
+ }
204
+ ]
205
+ suites: []
206
+ ]
207
+ }
208
+ ]
209
+ }
210
+
211
+ expect(@result).to.eql expected
212
+
213
+ describe 'when errors is :always', ->
214
+ beforeEach ->
215
+ @result = new Result(@resultObj, @logObj, @errorsObj, { console: 'never', errors: 'always' }).process()
216
+
217
+ it 'does add all the log statements to the specs', ->
218
+ expected = {
219
+ passed: false
220
+ stats:
221
+ failures: 1
222
+ specs: 4
223
+ time: 0.10
224
+ specs: [
225
+ {
226
+ description: "Spec 1"
227
+ passed: true
228
+ }
229
+ ]
230
+ suites: [
231
+ {
232
+ description: "Suite 1"
233
+ passed: true
234
+ specs: [
235
+ {
236
+ description: "Spec 2"
237
+ passed: true
238
+ errors: [{ msg: 'Failure 1', trace: { file: 'a file' }}]
239
+ }
240
+ {
241
+ description: "Spec 3"
242
+ passed: true
243
+ errors: [{ msg: 'Failure 2', trace: { file: 'another file' }}]
244
+ }
245
+ ]
246
+ suites: [
247
+ description: "Suite 2"
248
+ passed: false
249
+ specs: [
250
+ {
251
+ description: "Spec 4"
252
+ passed: false
253
+ errors: [{ msg: 'Failure 3', trace: { file: 'file' }}]
254
+ }
255
+ ]
256
+ suites: []
257
+ ]
258
+ }
259
+ ]
260
+ }
261
+
262
+ expect(@result).to.eql expected
263
+
264
+ describe 'when errors is :failure', ->
265
+ beforeEach ->
266
+ @result = new Result(@resultObj, @logObj, @errorsObj, { console: 'never', errors: 'failure' }).process()
267
+
268
+ it 'does add the log statements to the failing specs', ->
269
+ expected = {
270
+ passed: false
271
+ stats:
272
+ failures: 1
273
+ specs: 4
274
+ time: 0.10
275
+ specs: [
276
+ {
277
+ description: "Spec 1"
278
+ passed: true
279
+ }
280
+ ]
281
+ suites: [
282
+ {
283
+ description: "Suite 1"
284
+ passed: true
285
+ specs: [
286
+ {
287
+ description: "Spec 2"
288
+ passed: true
289
+ }
290
+ {
291
+ description: "Spec 3"
292
+ passed: true
293
+ }
294
+ ]
295
+ suites: [
296
+ description: "Suite 2"
297
+ passed: false
298
+ specs: [
299
+ {
300
+ description: "Spec 4"
301
+ passed: false
302
+ errors: [{ msg: 'Failure 3', trace: { file: 'file' }}]
303
+ }
304
+ ]
305
+ suites: []
306
+ ]
307
+ }
308
+ ]
309
+ }
310
+
311
+ expect(@result).to.eql expected
@@ -87,7 +87,7 @@ module Guard
87
87
  def run_jasmine_spec(file, options)
88
88
  suite = jasmine_suite(file, options)
89
89
  Formatter.info("Run Jasmine suite at #{ suite }")
90
- IO.popen("#{ phantomjs_command(options) } \"#{ suite }\" #{ options[:timeout] }")
90
+ IO.popen("#{ phantomjs_command(options) } \"#{ suite }\" #{ options[:timeout] } #{ options[:specdoc] } #{ options[:focus] } #{ options[:console] } #{ options[:errors] }")
91
91
  end
92
92
 
93
93
  # Get the PhantomJS binary and script to execute.
@@ -205,24 +205,30 @@ module Guard
205
205
  # @option options [Boolean] :hide_success hide success message notification
206
206
  #
207
207
  def notify_spec_result(result, options)
208
- specs = result['stats']['specs']
209
- failures = result['stats']['failures']
210
- time = result['stats']['time']
211
- plural = failures == 1 ? '' : 's'
212
-
213
- message = "#{ specs } specs, #{ failures } failure#{ plural }\nin #{ time } seconds"
214
- passed = failures == 0
215
-
208
+ specs = result['stats']['specs']
209
+ failures = result['stats']['failures']
210
+ time = result['stats']['time']
211
+ specs_plural = specs == 1 ? '' : 's'
212
+ failures_plural = failures == 1 ? '' : 's'
213
+
214
+ Formatter.info("\nFinished in #{ time } seconds")
215
+
216
+ message = "#{ specs } spec#{ specs_plural }, #{ failures } failure#{ failures_plural }"
217
+ full_message = "#{ message }\nin #{ time } seconds"
218
+ passed = failures == 0
219
+
216
220
  if passed
217
221
  report_specdoc(result, passed, options) if options[:specdoc] == :always
218
222
  Formatter.success(message)
219
- Formatter.notify(message, :title => 'Jasmine suite passed') if options[:notification] && !options[:hide_success]
223
+ Formatter.notify(full_message, :title => 'Jasmine suite passed') if options[:notification] && !options[:hide_success]
220
224
  else
221
225
  report_specdoc(result, passed, options) if options[:specdoc] != :never
222
226
  Formatter.error(message)
223
227
  notify_errors(result, options)
224
- Formatter.notify(message, :title => 'Jasmine suite failed', :image => :failed, :priority => 2) if options[:notification]
228
+ Formatter.notify(full_message, :title => 'Jasmine suite failed', :image => :failed, :priority => 2) if options[:notification]
225
229
  end
230
+
231
+ Formatter.info("Done.\n")
226
232
  end
227
233
 
228
234
  # Specdoc like formatting of the result.
@@ -261,6 +267,7 @@ module Guard
261
267
  spec['messages'].each do |message|
262
268
  Formatter.spec_failed(indent(" ➤ #{ format_message(message, false) }", level))
263
269
  end
270
+ report_specdoc_errors(spec, options, level)
264
271
  report_specdoc_logs(spec, options, level)
265
272
  end
266
273
  end
@@ -285,6 +292,25 @@ module Guard
285
292
  end
286
293
  end
287
294
 
295
+ # Shows the errors for a given spec.
296
+ #
297
+ # @param [Hash] spec the spec result
298
+ # @param [Hash] options the options
299
+ # @option options [Symbol] :errors options for the errors output, either :always, :never or :failure
300
+ # @param [Number] level the indention level
301
+ #
302
+ def report_specdoc_errors(spec, options, level)
303
+ if spec['errors'] && (options[:errors] == :always || (options[:errors] == :failure && !spec['passed']))
304
+ spec['errors'].each do |error|
305
+ if error['trace']
306
+ Formatter.spec_failed(indent(" ➜ Exception: #{ error['msg'] } in #{ error['trace']['file'] } on line #{ error['trace']['line'] }", level))
307
+ else
308
+ Formatter.spec_failed(indent(" ➜ Exception: #{ error['msg'] }", level))
309
+ end
310
+ end
311
+ end
312
+ end
313
+
288
314
  # Indent a message.
289
315
  #
290
316
  # @param [String] message the message
@@ -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.0.4'
4
+ VERSION = '1.1.0'
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guard-jasmine
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-13 00:00:00.000000000 Z
12
+ date: 2012-03-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: guard
16
- requirement: &70226386800360 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: 0.8.3
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70226386800360
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.8.3
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: multi_json
27
- requirement: &70226386799980 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *70226386799980
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: childprocess
38
- requirement: &70226386799440 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :runtime
45
55
  prerelease: false
46
- version_requirements: *70226386799440
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: thor
49
- requirement: &70226386799000 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,10 +69,15 @@ dependencies:
54
69
  version: '0'
55
70
  type: :runtime
56
71
  prerelease: false
57
- version_requirements: *70226386799000
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: bundler
60
- requirement: &70226386798540 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ! '>='
@@ -65,10 +85,15 @@ dependencies:
65
85
  version: '0'
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *70226386798540
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
69
94
  - !ruby/object:Gem::Dependency
70
95
  name: guard-rspec
71
- requirement: &70226386798120 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
72
97
  none: false
73
98
  requirements:
74
99
  - - ! '>='
@@ -76,10 +101,15 @@ dependencies:
76
101
  version: '0'
77
102
  type: :development
78
103
  prerelease: false
79
- version_requirements: *70226386798120
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
80
110
  - !ruby/object:Gem::Dependency
81
111
  name: guard-coffeescript
82
- requirement: &70226386797680 !ruby/object:Gem::Requirement
112
+ requirement: !ruby/object:Gem::Requirement
83
113
  none: false
84
114
  requirements:
85
115
  - - ! '>='
@@ -87,10 +117,15 @@ dependencies:
87
117
  version: '0'
88
118
  type: :development
89
119
  prerelease: false
90
- version_requirements: *70226386797680
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
91
126
  - !ruby/object:Gem::Dependency
92
127
  name: guard-shell
93
- requirement: &70226386797200 !ruby/object:Gem::Requirement
128
+ requirement: !ruby/object:Gem::Requirement
94
129
  none: false
95
130
  requirements:
96
131
  - - ! '>='
@@ -98,10 +133,15 @@ dependencies:
98
133
  version: '0'
99
134
  type: :development
100
135
  prerelease: false
101
- version_requirements: *70226386797200
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
102
142
  - !ruby/object:Gem::Dependency
103
143
  name: rspec
104
- requirement: &70226386796760 !ruby/object:Gem::Requirement
144
+ requirement: !ruby/object:Gem::Requirement
105
145
  none: false
106
146
  requirements:
107
147
  - - ! '>='
@@ -109,10 +149,15 @@ dependencies:
109
149
  version: '0'
110
150
  type: :development
111
151
  prerelease: false
112
- version_requirements: *70226386796760
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
113
158
  - !ruby/object:Gem::Dependency
114
159
  name: yard
115
- requirement: &70226386796320 !ruby/object:Gem::Requirement
160
+ requirement: !ruby/object:Gem::Requirement
116
161
  none: false
117
162
  requirements:
118
163
  - - ! '>='
@@ -120,10 +165,15 @@ dependencies:
120
165
  version: '0'
121
166
  type: :development
122
167
  prerelease: false
123
- version_requirements: *70226386796320
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
124
174
  - !ruby/object:Gem::Dependency
125
175
  name: redcarpet
126
- requirement: &70226386795880 !ruby/object:Gem::Requirement
176
+ requirement: !ruby/object:Gem::Requirement
127
177
  none: false
128
178
  requirements:
129
179
  - - ! '>='
@@ -131,10 +181,15 @@ dependencies:
131
181
  version: '0'
132
182
  type: :development
133
183
  prerelease: false
134
- version_requirements: *70226386795880
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
135
190
  - !ruby/object:Gem::Dependency
136
191
  name: pry
137
- requirement: &70226386795440 !ruby/object:Gem::Requirement
192
+ requirement: !ruby/object:Gem::Requirement
138
193
  none: false
139
194
  requirements:
140
195
  - - ! '>='
@@ -142,10 +197,15 @@ dependencies:
142
197
  version: '0'
143
198
  type: :development
144
199
  prerelease: false
145
- version_requirements: *70226386795440
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ! '>='
204
+ - !ruby/object:Gem::Version
205
+ version: '0'
146
206
  - !ruby/object:Gem::Dependency
147
207
  name: yajl-ruby
148
- requirement: &70226386795000 !ruby/object:Gem::Requirement
208
+ requirement: !ruby/object:Gem::Requirement
149
209
  none: false
150
210
  requirements:
151
211
  - - ! '>='
@@ -153,7 +213,12 @@ dependencies:
153
213
  version: '0'
154
214
  type: :development
155
215
  prerelease: false
156
- version_requirements: *70226386795000
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ! '>='
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
157
222
  description: Guard::Jasmine automatically tests your Jasmine specs on PhantomJS
158
223
  email:
159
224
  - michi@netzpiraten.ch
@@ -171,10 +236,13 @@ files:
171
236
  - lib/guard/jasmine/phantomjs/guard-jasmine.coffee
172
237
  - lib/guard/jasmine/phantomjs/lib/console.js
173
238
  - lib/guard/jasmine/phantomjs/lib/reporter.js
239
+ - lib/guard/jasmine/phantomjs/lib/result.js
174
240
  - lib/guard/jasmine/phantomjs/src/console.coffee
175
241
  - lib/guard/jasmine/phantomjs/src/reporter.coffee
242
+ - lib/guard/jasmine/phantomjs/src/result.coffee
176
243
  - lib/guard/jasmine/phantomjs/test/console_spec.coffee
177
244
  - lib/guard/jasmine/phantomjs/test/reporter_spec.coffee
245
+ - lib/guard/jasmine/phantomjs/test/result_spec.coffee
178
246
  - lib/guard/jasmine/runner.rb
179
247
  - lib/guard/jasmine/server.rb
180
248
  - lib/guard/jasmine/task.rb
@@ -204,7 +272,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
204
272
  version: 1.3.6
205
273
  requirements: []
206
274
  rubyforge_project: guard-jasmine
207
- rubygems_version: 1.8.17
275
+ rubygems_version: 1.8.19
208
276
  signing_key:
209
277
  specification_version: 3
210
278
  summary: Guard gem for headless testing with Jasmine