guard-jasmine 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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