guard-jasmine 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +13 -18
- data/lib/guard/jasmine.rb +91 -9
- data/lib/guard/jasmine/formatter.rb +18 -0
- data/lib/guard/jasmine/phantomjs/run-jasmine.coffee +73 -67
- data/lib/guard/jasmine/runner.rb +46 -23
- data/lib/guard/jasmine/version.rb +1 -1
- metadata +3 -3
data/README.md
CHANGED
@@ -135,6 +135,12 @@ There following options can be passed to Guard::Jasmine:
|
|
135
135
|
:all_on_start => false # Run all specs on start.
|
136
136
|
# default: true
|
137
137
|
|
138
|
+
:keep_failed => false # Keep failed specs and add them the next run again.
|
139
|
+
# default: true
|
140
|
+
|
141
|
+
:all_after_pass => false # Run all specs after a single spec has passed.
|
142
|
+
# default: true
|
143
|
+
|
138
144
|
:notifications => false # Show success and error messages.
|
139
145
|
# default: true
|
140
146
|
|
@@ -144,7 +150,7 @@ There following options can be passed to Guard::Jasmine:
|
|
144
150
|
|
145
151
|
## Alternatives
|
146
152
|
|
147
|
-
* [guard-jasmine-headless-webkit][], a Guard for [jasmine-headless-webkit][], but doesn't run
|
153
|
+
* [guard-jasmine-headless-webkit][], a Guard for [jasmine-headless-webkit][], but doesn't run on JRuby.
|
148
154
|
* [Evergreen][], runs CoffeeScript specs headless, but has no
|
149
155
|
continuous testing support.
|
150
156
|
* [Jezebel][] a Node.js REPL and continuous test runner for [Jessie][], a Node runner for Jasmine, but has no full
|
@@ -168,26 +174,17 @@ For questions please join us on our [Google group](http://groups.google.com/grou
|
|
168
174
|
|
169
175
|
## Acknowledgment
|
170
176
|
|
171
|
-
[Ariya Hidayat][] for [PhantomJS][], a powerfull headless WebKit browser.
|
172
|
-
|
173
|
-
[
|
174
|
-
|
175
|
-
[Pivotal Labs][] for their beautiful [Jasmine][] BDD testing framework that makes JavaScript testing fun.
|
176
|
-
|
177
|
-
[Jeremy Ashkenas][] for [CoffeeScript][], that little language that compiles into JavaScript and makes me enjoy the
|
177
|
+
- [Ariya Hidayat][] for [PhantomJS][], a powerfull headless WebKit browser.
|
178
|
+
- [Brad Phelan][] for [Jasminerice][], an elegant solution for [Jasmine][] in the Rails 3.1 asset pipeline.
|
179
|
+
- [Pivotal Labs][] for their beautiful [Jasmine][] BDD testing framework that makes JavaScript testing fun.
|
180
|
+
- [Jeremy Ashkenas][] for [CoffeeScript][], that little language that compiles into JavaScript and makes me enjoy the
|
178
181
|
frontend.
|
179
|
-
|
180
|
-
The [Guard Team][] for giving us such a nice piece of software that is so easy to extend, one *has* to make a plugin
|
182
|
+
- The [Guard Team][] for giving us such a nice piece of software that is so easy to extend, one *has* to make a plugin
|
181
183
|
for it!
|
182
|
-
|
183
|
-
All the authors of the numerous [Guards][] available for making the Guard ecosystem so much growing and comprehensive.
|
184
|
+
- All the authors of the numerous [Guards][] available for making the Guard ecosystem so much growing and comprehensive.
|
184
185
|
|
185
186
|
## License
|
186
187
|
|
187
|
-
The Jasmine PhantomJS runner file [run-jasmine.coffee][] from [Roejames12][] is licensed under the BSD license.
|
188
|
-
|
189
|
-
The Guard::Jasmine itself is released under:
|
190
|
-
|
191
188
|
(The MIT License)
|
192
189
|
|
193
190
|
Copyright (c) 2011 Michael Kessler
|
@@ -218,8 +215,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
218
215
|
[PhantomJS]: http://www.phantomjs.org/
|
219
216
|
[the PhantomJS download section]: http://code.google.com/p/phantomjs/downloads/list
|
220
217
|
[PhantomJS build instructions]: http://code.google.com/p/phantomjs/wiki/BuildInstructions
|
221
|
-
[Roejames12]: https://github.com/Roejames12
|
222
|
-
[run-jasmine.coffee]: https://github.com/ariya/phantomjs/blob/master/examples/run-jasmine.coffee
|
223
218
|
[Brad Phelan]: http://twitter.com/#!/bradgonesurfing
|
224
219
|
[Jasminerice]: https://github.com/bradphelan/jasminerice
|
225
220
|
[Pivotal Labs]: http://pivotallabs.com/
|
data/lib/guard/jasmine.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'guard'
|
2
2
|
require 'guard/guard'
|
3
3
|
require 'guard/watcher'
|
4
|
+
require 'net/http'
|
4
5
|
|
5
6
|
module Guard
|
6
7
|
|
@@ -13,6 +14,8 @@ module Guard
|
|
13
14
|
autoload :Inspector, 'guard/jasmine/inspector'
|
14
15
|
autoload :Runner, 'guard/jasmine/runner'
|
15
16
|
|
17
|
+
attr_accessor :last_run_failed, :last_failed_paths
|
18
|
+
|
16
19
|
# Initialize Guard::Jasmine.
|
17
20
|
#
|
18
21
|
# @param [Array<Guard::Watcher>] watchers the watchers in the Guard block
|
@@ -22,17 +25,24 @@ module Guard
|
|
22
25
|
# @option options [Boolean] :notification show notifications
|
23
26
|
# @option options [Boolean] :hide_success hide success message notification
|
24
27
|
# @option options [Boolean] :all_on_start run all suites on start
|
28
|
+
# @option options [Boolean] :keep_failed keep failed specs and add them the next run again
|
29
|
+
# @option options [Boolean] :all_after_pass run all specs after a single spec has passed
|
25
30
|
#
|
26
31
|
def initialize(watchers = [], options = { })
|
27
32
|
defaults = {
|
28
|
-
:jasmine_url
|
29
|
-
:phantomjs_bin
|
30
|
-
:notification
|
31
|
-
:hide_success
|
32
|
-
:all_on_start
|
33
|
+
:jasmine_url => 'http://localhost:3000/jasmine',
|
34
|
+
:phantomjs_bin => '/usr/local/bin/phantomjs',
|
35
|
+
:notification => true,
|
36
|
+
:hide_success => false,
|
37
|
+
:all_on_start => true,
|
38
|
+
:keep_failed => true,
|
39
|
+
:all_after_pass => true
|
33
40
|
}
|
34
41
|
|
35
42
|
super(watchers, defaults.merge(options))
|
43
|
+
|
44
|
+
self.last_run_failed = false
|
45
|
+
self.last_failed_paths = []
|
36
46
|
end
|
37
47
|
|
38
48
|
# Gets called once when Guard starts.
|
@@ -40,7 +50,20 @@ module Guard
|
|
40
50
|
# @return [Boolean] when the start was successful
|
41
51
|
#
|
42
52
|
def start
|
43
|
-
|
53
|
+
if jasmine_runner_available?(options[:jasmine_url])
|
54
|
+
run_all if options[:all_on_start]
|
55
|
+
end
|
56
|
+
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
# Gets called when the Guard should reload itself.
|
61
|
+
#
|
62
|
+
# @return [Boolean] when the reload was successful
|
63
|
+
#
|
64
|
+
def reload
|
65
|
+
self.last_run_failed = false
|
66
|
+
self.last_failed_paths = []
|
44
67
|
|
45
68
|
true
|
46
69
|
end
|
@@ -50,7 +73,12 @@ module Guard
|
|
50
73
|
# @return [Boolean] when running all specs was successful
|
51
74
|
#
|
52
75
|
def run_all
|
53
|
-
Runner.run(['spec/javascripts'], options)
|
76
|
+
passed, failed_specs = Runner.run(['spec/javascripts'], options)
|
77
|
+
|
78
|
+
self.last_failed_paths = failed_specs
|
79
|
+
self.last_run_failed = !passed
|
80
|
+
|
81
|
+
passed
|
54
82
|
end
|
55
83
|
|
56
84
|
# Gets called when watched paths and files have changes.
|
@@ -59,9 +87,63 @@ module Guard
|
|
59
87
|
# @return [Boolean] when running the changed specs was successful
|
60
88
|
#
|
61
89
|
def run_on_change(paths)
|
62
|
-
|
90
|
+
paths += self.last_failed_paths if options[:keep_failed]
|
91
|
+
|
92
|
+
passed, failed_specs = Runner.run(Inspector.clean(paths), options)
|
63
93
|
|
64
|
-
|
94
|
+
if passed
|
95
|
+
self.last_failed_paths = self.last_failed_paths - paths
|
96
|
+
run_all if self.last_run_failed && options[:all_after_pass]
|
97
|
+
else
|
98
|
+
self.last_failed_paths = self.last_failed_paths + failed_specs
|
99
|
+
end
|
100
|
+
|
101
|
+
self.last_run_failed = !passed
|
102
|
+
|
103
|
+
passed
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
# Verifies if the Jasmine test runner is available.
|
109
|
+
#
|
110
|
+
# @param [String] url the location of the test runner
|
111
|
+
# @return [Boolean] when the runner is available
|
112
|
+
#
|
113
|
+
def jasmine_runner_available?(url)
|
114
|
+
url = URI.parse(url)
|
115
|
+
|
116
|
+
begin
|
117
|
+
Net::HTTP.start(url.host, url.port) do |http|
|
118
|
+
response = http.request(Net::HTTP::Head.new(url.path))
|
119
|
+
|
120
|
+
if response.code.to_i == 200
|
121
|
+
Formatter.info("Jasmine test runner is available at #{ url }")
|
122
|
+
else
|
123
|
+
notify_jasmine_runner_failure(url) if options[:notification]
|
124
|
+
end
|
125
|
+
|
126
|
+
response.code.to_i == 200
|
127
|
+
end
|
128
|
+
|
129
|
+
rescue Errno::ECONNREFUSED => e
|
130
|
+
notify_jasmine_runner_failure(url)
|
131
|
+
|
132
|
+
false
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Notify that the Jasmine runner is not available.
|
137
|
+
#
|
138
|
+
# @param [String] url the url of the Jasmine runner
|
139
|
+
#
|
140
|
+
def notify_jasmine_runner_failure(url)
|
141
|
+
message = "Jasmine test runner not available at #{ url }"
|
142
|
+
Formatter.error(message)
|
143
|
+
Formatter.notify(message,
|
144
|
+
:title => 'Jasmine test runner not available',
|
145
|
+
:image => :failed,
|
146
|
+
:priority => 2)
|
65
147
|
end
|
66
148
|
|
67
149
|
end
|
@@ -48,6 +48,24 @@ module Guard
|
|
48
48
|
::Guard::UI.info(color(message, ';32'), options)
|
49
49
|
end
|
50
50
|
|
51
|
+
# Print a red spec failed message to the console.
|
52
|
+
#
|
53
|
+
# @param [String] message the message to print
|
54
|
+
# @param [Hash] options the output options
|
55
|
+
#
|
56
|
+
def spec_failed(message, options = { })
|
57
|
+
::Guard::UI.info(color(message, ';31'), options)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Print a red spec failed message to the console.
|
61
|
+
#
|
62
|
+
# @param [String] message the message to print
|
63
|
+
# @param [Hash] options the output options
|
64
|
+
#
|
65
|
+
def suite_name(message, options = { })
|
66
|
+
::Guard::UI.info(color(message, ';33'), options)
|
67
|
+
end
|
68
|
+
|
51
69
|
# Outputs a system notification.
|
52
70
|
#
|
53
71
|
# @param [String] message the message to print
|
@@ -1,29 +1,85 @@
|
|
1
|
+
# This file is the script that runs within PhantomJS and requests the Jasmine specs,
|
2
|
+
# waits until they are ready, extracts the result form the dom and outputs a JSON
|
3
|
+
# structure that is the parsed by Guard::Jasmine.
|
4
|
+
#
|
5
|
+
# This scripts needs the TrivialReporter to report the results.
|
6
|
+
#
|
7
|
+
# This file is inspired by the Jasmine runner that comes with the PhantomJS examples:
|
8
|
+
# https://github.com/ariya/phantomjs/blob/master/examples/run-jasmine.coffee, by https://github.com/Roejames12
|
9
|
+
#
|
10
|
+
# This file is licensed under the BSD license.
|
11
|
+
|
1
12
|
# Wait until the test condition is true or a timeout occurs.
|
2
13
|
#
|
3
|
-
# @param [Function]
|
4
|
-
# @param [Function]
|
5
|
-
# @param [Number]
|
14
|
+
# @param [Function] condition the condition that evaluates to a boolean
|
15
|
+
# @param [Function] ready the action when the condition is fulfilled
|
16
|
+
# @param [Number] timeout the max amount of time to wait
|
6
17
|
#
|
7
|
-
waitFor = (
|
18
|
+
waitFor = (condition, ready, timeout = 3000) ->
|
8
19
|
start = new Date().getTime()
|
9
|
-
condition = false
|
10
20
|
wait = ->
|
11
|
-
if
|
12
|
-
|
21
|
+
if new Date().getTime() - start > timeout
|
22
|
+
console.log JSON.stringify({ error: "Timeout requesting Jasmine test runner!" })
|
23
|
+
phantom.exit(1)
|
13
24
|
else
|
14
|
-
if
|
15
|
-
|
16
|
-
phantom.exit(1)
|
17
|
-
else
|
18
|
-
if typeof onReady is 'string' then eval onReady else onReady()
|
25
|
+
if condition()
|
26
|
+
ready()
|
19
27
|
clearInterval interval
|
20
28
|
|
21
29
|
interval = setInterval wait, 100
|
22
30
|
|
31
|
+
# Test if the specs have finished.
|
32
|
+
#
|
33
|
+
specsReady = ->
|
34
|
+
page.evaluate -> if document.body.querySelector('.finished-at') then true else false
|
35
|
+
|
36
|
+
# Extract the data from a Jasmine TrivialReporter generated DOM
|
37
|
+
#
|
38
|
+
extractResult = ->
|
39
|
+
page.evaluate ->
|
40
|
+
stats = /(\d+) specs, (\d+) failures? in (\d+.\d+)s/.exec document.body.querySelector('.description').innerText
|
41
|
+
|
42
|
+
result = {
|
43
|
+
passed: true
|
44
|
+
stats: {
|
45
|
+
specs: parseInt stats[1]
|
46
|
+
failures: parseInt stats[2]
|
47
|
+
time: parseFloat stats[3]
|
48
|
+
}
|
49
|
+
suites: []
|
50
|
+
}
|
51
|
+
|
52
|
+
for suite in document.body.querySelectorAll('div.jasmine_reporter > div.suite')
|
53
|
+
description = suite.querySelector('a.description')
|
54
|
+
|
55
|
+
suite_ = {
|
56
|
+
description: description.innerText
|
57
|
+
specs: []
|
58
|
+
}
|
59
|
+
|
60
|
+
for spec in suite.querySelectorAll('div.spec')
|
61
|
+
passed = spec.getAttribute('class').indexOf('passed') isnt -1
|
62
|
+
result['passed'] = false if not passed
|
63
|
+
|
64
|
+
spec_ = {
|
65
|
+
description: spec.querySelector('a.description').getAttribute 'title'
|
66
|
+
passed: passed
|
67
|
+
}
|
68
|
+
|
69
|
+
spec_['error_message'] = spec.querySelector('div.resultMessage').innerText if not passed
|
70
|
+
|
71
|
+
suite_['specs'].push spec_
|
72
|
+
|
73
|
+
result['suites'].push suite_
|
74
|
+
|
75
|
+
console.log "JSON_RESULT: #{ JSON.stringify(result, undefined, 2) }"
|
76
|
+
|
77
|
+
phantom.exit()
|
78
|
+
|
23
79
|
# Check arguments of the script.
|
24
80
|
#
|
25
81
|
if phantom.args.length isnt 1
|
26
|
-
console.log JSON.stringify
|
82
|
+
console.log JSON.stringify({ error: "Wrong usage of PhantomJS script!" })
|
27
83
|
phantom.exit()
|
28
84
|
else
|
29
85
|
url = phantom.args[0]
|
@@ -31,66 +87,16 @@ else
|
|
31
87
|
page = new WebPage()
|
32
88
|
|
33
89
|
# Output the Jasmine test runner result as JSON object.
|
34
|
-
# Ignore all other calls to console.log
|
90
|
+
# Ignore all other calls to console.log that may come from the specs.
|
35
91
|
#
|
36
92
|
page.onConsoleMessage = (msg) ->
|
37
|
-
console.log(RegExp.$1) if /^
|
93
|
+
console.log(RegExp.$1) if /^JSON_RESULT: ([\s\S]*)$/.test(msg)
|
38
94
|
|
39
95
|
# Open web page and run the Jasmine test runner
|
40
96
|
#
|
41
97
|
page.open url, (status) ->
|
42
|
-
|
43
98
|
if status isnt 'success'
|
44
|
-
|
45
|
-
console.log "JasmineResult: #{ JSON.stringify { error: "Unable to access Jasmine specs at #{ url }" } }"
|
99
|
+
console.log "JSON_RESULT: #{ JSON.stringify({ error: "Unable to access Jasmine specs at #{ url }" }) }"
|
46
100
|
phantom.exit()
|
47
|
-
|
48
101
|
else
|
49
|
-
|
50
|
-
waitFor ->
|
51
|
-
page.evaluate ->
|
52
|
-
if document.body.querySelector '.finished-at' then true else false
|
53
|
-
, ->
|
54
|
-
# Jasmine test runner has finished, extract the result from the DOM
|
55
|
-
page.evaluate ->
|
56
|
-
|
57
|
-
# JSON response to Guard::Jasmine
|
58
|
-
result = {
|
59
|
-
suites: []
|
60
|
-
}
|
61
|
-
|
62
|
-
# Extract runner stats from the HTML
|
63
|
-
stats = /(\d+) specs, (\d+) failures? in (\d+.\d+)s/.exec document.body.querySelector('.description').innerText
|
64
|
-
|
65
|
-
# Add stats to the result
|
66
|
-
result['stats'] = {
|
67
|
-
specs: parseInt stats[1]
|
68
|
-
failures: parseInt stats[2]
|
69
|
-
time: parseFloat stats[3]
|
70
|
-
}
|
71
|
-
|
72
|
-
# Extract failed suites
|
73
|
-
for failedSuite in document.body.querySelectorAll 'div.jasmine_reporter > div.suite.failed'
|
74
|
-
description = failedSuite.querySelector('a.description')
|
75
|
-
|
76
|
-
# Add suite information to the result
|
77
|
-
suite = {
|
78
|
-
description: description.innerText
|
79
|
-
filter: description.getAttribute('href')
|
80
|
-
specs: []
|
81
|
-
}
|
82
|
-
|
83
|
-
# Collect information about each **failing** spec
|
84
|
-
for failedSpec in failedSuite.querySelectorAll 'div.spec.failed'
|
85
|
-
spec = {
|
86
|
-
description: failedSpec.querySelector('a.description').getAttribute 'title'
|
87
|
-
error_message: failedSpec.querySelector('div.messages div.resultMessage').innerText
|
88
|
-
}
|
89
|
-
suite['specs'].push spec
|
90
|
-
|
91
|
-
result['suites'].push suite
|
92
|
-
|
93
|
-
# Write result as JSON string that is parsed by Guard::Jasmine
|
94
|
-
console.log "JasmineResult: #{ JSON.stringify result, undefined, 2 }"
|
95
|
-
|
96
|
-
phantom.exit()
|
102
|
+
waitFor specsReady, extractResult
|
data/lib/guard/jasmine/runner.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
1
3
|
require 'multi_json'
|
2
4
|
|
3
5
|
module Guard
|
@@ -18,30 +20,50 @@ module Guard
|
|
18
20
|
# @option options [String] :phantomjs_bin the location of the PhantomJS binary
|
19
21
|
# @option options [Boolean] :notification show notifications
|
20
22
|
# @option options [Boolean] :hide_success hide success message notification
|
21
|
-
# @return [Array<
|
23
|
+
# @return [Boolean, Array<String>] the status of the run and the failed files
|
22
24
|
#
|
23
25
|
def run(paths, options = { })
|
24
|
-
return false if paths.empty?
|
26
|
+
return [false, []] if paths.empty?
|
25
27
|
|
26
28
|
message = options[:message] || (paths == ['spec/javascripts'] ? 'Run all specs' : "Run specs #{ paths.join(' ') }")
|
27
29
|
UI.info message, :reset => true
|
28
30
|
|
29
|
-
paths.inject([]) do |results, file|
|
30
|
-
results << evaluate_result(run_jasmine_spec(file, options), options)
|
31
|
+
results = paths.inject([]) do |results, file|
|
32
|
+
results << evaluate_result(run_jasmine_spec(file, options), file, options)
|
31
33
|
|
32
34
|
results
|
33
35
|
end.compact
|
36
|
+
|
37
|
+
[response_status_for(results), failed_paths_from(results)]
|
34
38
|
end
|
35
39
|
|
36
40
|
private
|
37
41
|
|
42
|
+
# Returns the failed spec file names.
|
43
|
+
#
|
44
|
+
# @param [Array<Object>] results the spec runner results
|
45
|
+
# @return [Array<String>] the list of failed spec files
|
46
|
+
#
|
47
|
+
def failed_paths_from(results)
|
48
|
+
results.map { |r| !r['passed'] ? r['file']: nil }.compact
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns the response status for the given result set.
|
52
|
+
#
|
53
|
+
# @param [Array<Object>] results the spec runner results
|
54
|
+
# @return [Boolean] whether it has passed or not
|
55
|
+
#
|
56
|
+
def response_status_for(results)
|
57
|
+
results.none? { |r| r.has_key?('error') || !r['passed'] }
|
58
|
+
end
|
59
|
+
|
38
60
|
# Run the Jasmine spec by executing the PhantomJS script.
|
39
61
|
#
|
40
62
|
# @param [String] path the path of the spec
|
41
63
|
#
|
42
64
|
def run_jasmine_spec(file, options)
|
43
65
|
suite = jasmine_suite(file, options)
|
44
|
-
Formatter.info("Run Jasmine tests
|
66
|
+
Formatter.info("Run Jasmine tests at #{ suite }")
|
45
67
|
IO.popen(phantomjs_command(options) + ' ' + suite)
|
46
68
|
end
|
47
69
|
|
@@ -101,16 +123,18 @@ module Guard
|
|
101
123
|
# actions.
|
102
124
|
#
|
103
125
|
# @param [String] output the JSON output the spec run
|
126
|
+
# @param [String] file the file name of the spec
|
104
127
|
# @param [Hash] options the options for the execution
|
105
128
|
# @return [Hash] the suite result
|
106
129
|
#
|
107
|
-
def evaluate_result(output, options)
|
130
|
+
def evaluate_result(output, file, options)
|
108
131
|
result = MultiJson.decode(output.read)
|
109
132
|
output.close
|
110
133
|
|
111
134
|
if result['error']
|
112
135
|
notify_runtime_error(result, options)
|
113
136
|
else
|
137
|
+
result['file'] = file
|
114
138
|
notify_spec_result(result, options)
|
115
139
|
end
|
116
140
|
|
@@ -144,39 +168,38 @@ module Guard
|
|
144
168
|
time = result['stats']['time']
|
145
169
|
plural = failures == 1 ? '' : 's'
|
146
170
|
|
147
|
-
message = "
|
171
|
+
message = "#{ specs } specs, #{ failures } failure#{ plural }\nin #{ time } seconds"
|
148
172
|
|
149
173
|
if failures != 0
|
150
|
-
|
174
|
+
notify_specdoc(result, message, options)
|
151
175
|
else
|
152
176
|
Formatter.success(message)
|
153
|
-
Formatter.notify(message, :title => 'Jasmine
|
177
|
+
Formatter.notify(message, :title => 'Jasmine specs passed') if options[:notification] && !options[:hide_success]
|
154
178
|
end
|
155
179
|
end
|
156
180
|
|
157
|
-
#
|
158
|
-
# error messages into a single notification.
|
181
|
+
# Specdoc like formatting of the result.
|
159
182
|
#
|
160
183
|
# @param [Hash] result the suite result
|
161
184
|
# @param [String] stats the status information
|
162
|
-
# @
|
163
|
-
# @option options [Boolean] :notification show notifications
|
185
|
+
# @option options [Boolean] :hide_success hide success message notification
|
164
186
|
#
|
165
|
-
def
|
166
|
-
|
187
|
+
def notify_specdoc(result, stats, options)
|
188
|
+
result['suites'].each do |suite|
|
189
|
+
Formatter.suite_name("➥ #{ suite['description'] }")
|
190
|
+
|
167
191
|
suite['specs'].each do |spec|
|
168
|
-
|
192
|
+
if spec['passed']
|
193
|
+
Formatter.success(" ✔ #{ spec['description'] }") if !options[:hide_success]
|
194
|
+
else
|
195
|
+
Formatter.spec_failed(" ✘ #{ spec['description'] } ➤ #{ spec['error_message'] }")
|
196
|
+
Formatter.notify(stats, :title => "#{ spec['description'] }: #{ spec['error_message'] }", :image => :failed, :priority => 2) if options[:notification]
|
197
|
+
end
|
169
198
|
end
|
170
|
-
|
171
|
-
messages
|
172
199
|
end
|
173
200
|
|
174
|
-
|
175
|
-
|
176
|
-
Formatter.error(messages)
|
177
|
-
Formatter.notify(messages, :title => 'Jasmine results', :image => :failed, :priority => 2) if options[:notification]
|
201
|
+
Formatter.info(stats)
|
178
202
|
end
|
179
|
-
|
180
203
|
end
|
181
204
|
end
|
182
205
|
end
|